public void CalculateCoverage_FileExists_WithLines_ReturnsCodeCoverageTable()
        {
            var annotations = new[]
            {
                new { fileName = "first", id = 1, index = 2, hitCount = 1, coverage = 100.0m, line = "first_1" },
                new { fileName = "second", id = 2, index = 8, hitCount = 3, coverage = 100.0m, line = "second_2" },
                new { fileName = "third", id = 3, index = 13, hitCount = 0, coverage = 0.0m, line = string.Empty }
            };

            var annotationTable = new AnnotationTable();
            foreach (var a in annotations)
            {
                annotationTable.Add(a.fileName);
                annotationTable[a.fileName].Add(new Annotation(a.id, a.index, a.hitCount));
            }

            var calculator = new CodeCoverageCalculator(null, annotationTable)
            {
                FileReader = new StubFileReader
                {
                    ExistsValue = true,
                    GetLinesValue = annotations.Select(a => a.line)
                }
            };

            var actualCoverage = calculator.CalculateCoverage();

            var expectedCoverage = new CodeCoverageTable
            {
                Total = (decimal)2 / 3 * 100
            };

            foreach (var a in annotations)
                expectedCoverage.Add(a.fileName, a.coverage);

            Assert.AreEqual(expectedCoverage.Plugin, actualCoverage.Plugin);
            Assert.AreEqual(expectedCoverage.Total, actualCoverage.Total);
            Assert.AreEqual(expectedCoverage.ToString(), actualCoverage.ToString());
            CollectionAssert.AreEqual(expectedCoverage, actualCoverage);
        }
        public void CalculateCoverage_DoNotReadAnnotations_ReturnsCodeCoverageTable()
        {
            var annotations = new[]
            {
                new { fileName = "first", hitCount = 3, totalCount = 3, coverage = 100.0m, line = "first_1" },
                new { fileName = "second", hitCount = 4, totalCount = 5, coverage = 80.0m, line = "second_2" },
                new { fileName = "third", hitCount = 8, totalCount = 10, coverage = 80.0m, line = "third_3" },
                new { fileName = "fourth", hitCount = 1, totalCount = 5, coverage = 20.0m, line = "fourth_4" },
                new { fileName = "fifth", hitCount = 3, totalCount = 30, coverage = 10.0m, line = "fifth_5" }
            };

            var annotationTable = new AnnotationTable();
            int id = 0;
            foreach (var a in annotations)
            {
                annotationTable.Add(a.fileName);
                int hitCount = a.hitCount;
                for (int i = 0; i < a.totalCount; i++)
                    annotationTable[a.fileName].Add(new Annotation(id++, id, hitCount-- > 0 ? 1 : 0));
            }

            var calculator = new CodeCoverageCalculator(annotationTable);

            var actualCoverage = calculator.CalculateCoverage(false);

            var expectedCoverage = new CodeCoverageTable
            {
                Total = 35.84905660377358490566037736m
            };

            foreach (var a in annotations)
                expectedCoverage.Add(a.fileName, a.coverage);

            Assert.AreEqual(expectedCoverage.Plugin, actualCoverage.Plugin);
            Assert.AreEqual(expectedCoverage.Total, actualCoverage.Total);
            Assert.AreEqual(expectedCoverage.ToString(), actualCoverage.ToString());
            CollectionAssert.AreEqual(expectedCoverage, actualCoverage);
        }
        public CodeCoverageTable LoadCoverage()
        {
            var report =
                GetTestReports()
                .First()
                .GetFiles()
                .FirstOrDefault(x => x.FullName.ToLower().EndsWith("annotation.axml"));

            var table = PluginAnnotationTable.Load(report.FullName);
            var annotationTable = table.Items.First();

            var calculator = new CodeCoverageCalculator(annotationTable);
            return calculator.CalculateCoverage(false);
        }
        public void CalculateCoverage_FileExists_WithoutLines_ReturnsDefault()
        {
            var calculator = new CodeCoverageCalculator(null, new AnnotationTable())
            {
                FileReader = new StubFileReader
                {
                    ExistsValue = false
                }
            };

            var coverageTable = calculator.CalculateCoverage();

            Assert.AreEqual(new CodeCoverageTable(), coverageTable);
        }
示例#5
0
        static void ScanDirectory(DirectoryInfo AppDirectory, string RelativeAppPath)
        {
            var ignoreExtensions = new[]
            {
                "png",
                "jpg",
                "jpeg",
                "gif",
                "ico",
                "js",
                "css",
            };

            var urlDictionary = CreateUrlDictionary(RelativeAppPath, AppDirectory);

            var urlCollections = new[]
            {
                urlDictionary.Select(x => x.Key).ToList(),
                new List<string>()
            };

            var traceTable = new TraceTable();
            var report = new StringBuilder();
            var coverageReport = new StringBuilder();
            var map = new ApplicationMap();
            var alerts = new ScanAlertCollection();
            int requestCount = 0;
            MessageDumper messageDumper = null;

            if (Config.DumpMessages)
            {
                messageDumper = new MessageDumper(_reportWriter.ReportPath.FullName);
            }

            for (int urlCollectionIndex = 0; urlCollectionIndex < 2; urlCollectionIndex++)
                foreach (ScanPluginBase plugin in Config.ScanPlugins)
                {
                    if (Config.CodeCoverageReport > 0)
                    {
                        ScanMetrics.Default.Annotator.Reset();
                        ScanMetrics.Default.Annotator.AnnotationTable = ScanMetrics.Default.PluginAnnotations[plugin.ToString()];
                    }

                    if (!urlCollections[urlCollectionIndex].Any())
                        continue;

                    ScannerCli.DisplayScanPlugin(plugin);

                    foreach (var remotePath in urlCollections[urlCollectionIndex])
                    {
                        ScannerCli.DisplayResourcePath(remotePath);

                        IEnumerable<IEnumerable<TracedFunctionCall>> calls = null;
                        if (urlCollectionIndex == 0)
                        {
                            var key = urlDictionary[remotePath];

                            if (Program.PageFieldTable.ContainsKey(key))
                                calls = Program.PageFieldTable[key]
                                    .Select(x => x.Value.Select(y => new TracedFunctionCall()
                                    {
                                        Name = x.Key,
                                        ParameterValues = new List<string>() { y }
                                    }));
                        }

                        for (int i = 0; i < plugin.ModeCount; i++)
                        {
                            foreach (var useStaticAnalysisInputs in new[]
                        {
                            false,
                            true
                        })
                            {
                                var trace = new FileTrace();

                                if (useStaticAnalysisInputs && calls != null)
                                {
                                    if (!calls.Any(x => x.Any()))
                                        continue;

                                    foreach (var c in calls)
                                        trace.Calls.AddRange(c);
                                }

                                bool discoveredVars = true;

                                while (discoveredVars)
                                {
                                    var traceFile = new FileInfo(TraceFileName);

                                    IOHelper.TryAction(traceFile.Delete);

                                    var client = new TcpClient()
                                    {
                                        ReceiveTimeout = Config.Timeout,
                                        SendTimeout = Config.Timeout
                                    };

                                    while (!client.Connected)
                                        try
                                        {
                                            client.Connect(Config.Server, Config.Port);
                                        }
                                        catch (SocketException ex)
                                        {
                                            ScannerCli.DisplayError(ex.Message);

                                            Thread.Sleep(5000);
                                        }

                                    client.LingerState = new LingerOption(true, 0);
                                    HttpResponse resp = null;
                                    string req, respString = "";

                                    using (var stream = client.GetStream())
                                    {
                                        req = plugin.BuildRequest(i, remotePath, trace);

                                        if (Config.DumpMessages)
                                        {
                                            messageDumper.Dump(req, requestCount, MessageType.Request);
                                        }

                                        var stopwatch = new Stopwatch();
                                        stopwatch.Start();
                                        stream.WriteString(req);

                                        try
                                        {
                                            var sgs = trace.Calls
                                                .Superglobals()
                                                .Select(x => new { x.Name, Value = x.ParameterValues.Count > 0 ? x.ParameterValues[0] : null })
                                                .Distinct();

                                            var discoveredVarCount = sgs.Count();
                                            var reader = new HttpResponseReader(stream);
                                            resp = reader.Read();
                                            stopwatch.Stop();
                                            respString = resp.CompleteResponse;

                                            ScannerCli.DisplayResponse(
                                                resp,
                                                i,
                                                discoveredVarCount,
                                                stopwatch.ElapsedMilliseconds,
                                                resp.CompleteResponse.Length);
                                        }
                                        catch (SocketException)
                                        {
                                            ScannerCli.DisplayResponseError(respString);
                                        }
                                        catch (IOException)
                                        {
                                            ScannerCli.DisplayResponseError(respString);
                                        }
                                    }

                                    if (urlCollectionIndex == 0 && resp != null)
                                    {
                                        var abs = "http://" + Config.Server + remotePath;

                                        var urls = new UriScraper()
                                        {
                                            Regex = new Regex(@"[/.]" + Config.Server + @"($|/)", RegexOptions.IgnoreCase | RegexOptions.Compiled),
                                        }
                                        .Parse(resp.Body, abs)
                                        .Select(x => new Uri(x).LocalPath);

                                        foreach (var url in urls)
                                        {
                                            if (!ignoreExtensions.Any(x => url.ToLower().EndsWith("." + x)) &&
                                                !urlCollections[0].Contains(url) &&
                                                !urlCollections[1].Contains(url))
                                            {
                                                urlCollections[1].Add(url);

                                                ScannerCli.DisplayDiscoveredUrl(url);
                                            }
                                        }
                                    }

                                    client.Close();

                                    if (Config.DumpMessages)
                                    {
                                        messageDumper.Dump(respString, requestCount, MessageType.Response);
                                    }

                                    requestCount++;
                                    traceFile = new FileInfo(TraceFileName);
                                    FileTrace newTrace = null;

                                    IOHelper.TryAction(() =>
                                    {
                                        if (traceFile.Exists)
                                            using (var reader = traceFile.OpenText())
                                                newTrace = FileTrace.Parse(reader);
                                    });

                                    if (newTrace == null)
                                    {
                                        newTrace = new FileTrace();
                                    }

                                    newTrace.Request = req;
                                    newTrace.Response = respString;
                                    newTrace.File = remotePath;

                                    var alert = plugin.ScanTrace(newTrace);

                                    if (alert != null)
                                    {
                                        if (Config.BeepOnAlert)
                                            Console.Beep();

                                        ScannerCli.DisplayAlert(alert);

                                        alerts.Add(alert);
                                        report.Append(alert.ToString());
                                    }

                                    discoveredVars = false;

                                    foreach (TracedFunctionCall c in newTrace.Calls
                                        .Superglobals()
                                        .Where(x => x.ParameterValues.Any()))
                                    {
                                        var oldCalls = trace.Calls.Where(x =>
                                            x.Name == c.Name &&
                                            x.ParameterValues.SequenceEqual(c.ParameterValues));
                                        if (!oldCalls.Any())
                                        {
                                            discoveredVars = true;
                                            break;
                                        }
                                    }

                                    var orphanedInputs = trace.Calls
                                        .Superglobals()
                                        .Where(x => !newTrace.Calls
                                            .Any(y => x.Name == y.Name && x.ParameterValues
                                                .SequenceEqual(y.ParameterValues)))
                                        .ToArray();

                                    newTrace.Calls.AddRange(orphanedInputs);
                                    trace = newTrace;
                                }

                                var superglobals = trace.Calls.Superglobals();

                                map.AddTrace(trace);

                                if (Config.DiscoveryReport)
                                {
                                    if (!traceTable.ContainsKey(plugin))
                                    {
                                        traceTable.Add(plugin, new Dictionary<int, Dictionary<string, FileTrace>>());
                                    }

                                    if (!traceTable[plugin].ContainsKey(i))
                                    {
                                        traceTable[plugin].Add(i, new Dictionary<string, FileTrace>());
                                    }

                                    if (!traceTable[plugin][i].ContainsKey(trace.File))
                                    {
                                        traceTable[plugin][i].Add(trace.File, trace);
                                    }
                                    else
                                    {
                                        traceTable[plugin][i][trace.File] = trace;
                                    }
                                }
                            }
                        }
                    }

                    if (Config.CodeCoverageReport > 0 && urlCollectionIndex == 0)
                    {
                        Cli.WriteLine("Calculating code coverage...");
                        CodeCoverageTable coverage = null;

                        IOHelper.TryAction(() =>
                        {
                            var calculator = new CodeCoverageCalculator(
                                ScanMetrics.Default.Annotator.AnnotationFile,
                                ScanMetrics.Default.PluginAnnotations[plugin.ToString()]);
                            coverage = calculator.CalculateCoverage();
                        });

                        coverage.Plugin = plugin.ToString();
                        coverageReport.AppendLine(coverage.ToString() + "\r\n");
                    }

                    Cli.WriteLine();
                }

            _reportWriter.Write("Vulnerability Report", report.ToString());
            _reportWriter.Write("Input Map Report", map.ToXml(), "xml");

            if (alerts.Any())
            {
                _reportWriter.Write("Vulnerability Report",
                    alerts.ToXml(), "pxml");
            }

            if (Config.DiscoveryReport)
            {
                _reportWriter.Write("Scan Overview Report",
                    DiscoveryReport.Create(traceTable));
            }

            if (Config.CodeCoverageReport > 0)
            {
                _reportWriter.Write("Code Coverage Report", coverageReport.ToString());
                var annotationXml = ScanMetrics.Default.PluginAnnotations.ToXml();

                var annotationFile = _reportWriter.Write(
                    "Annotation",
                    annotationXml,
                    "axml");

                Cli.WriteLine();
                var commenter = new CoverageCommenter(ScanMetrics.Default.PluginAnnotations);
                commenter.LoadTable(annotationFile);
                commenter.WriteCommentedFiles(_reportWriter.ReportPath.FullName);

                _reportWriter.ReportFiles.Add(
                    new ReportFile(
                        "Coverage Comments",
                        Path.Combine("Code Coverage", "index.html")));
            }
        }