示例#1
0
        public void AddTrace(FileTrace Trace)
        {
            if (!Trace.Calls.Any())
            {
                return;
            }

            var page = Pages.SingleOrDefault(x => x.Page == Trace.File);

            if (page == null)
            {
                page = new ApplicationMapPage()
                {
                    Page = Trace.File
                };

                Pages.Add(page);
            }

            foreach (var superglobal in Php.Superglobals)
            {
                var fields      = page.SuperglobalNameCollectionTable[superglobal];
                var traceFields = Trace.Calls
                                  .Where(x => x.ParameterValues.Any() && x.Name == superglobal && !fields.Contains(x.ParameterValues[0]))
                                  .Select(x => x.ParameterValues[0]);

                if (!traceFields.Any())
                {
                    continue;
                }

                fields.AddRange(traceFields);
            }
        }
        public static FileTrace Parse(StreamReader Reader)
        {
            var trace = new FileTrace();
            var Text = Reader.ReadToEnd();
            trace.RawText = Text;

            var functions = Text.Split(new string[]
            {
                "--------------------------------Start\n",
                "--------------------------------End\n",
            }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var f in functions)
            {
                var call = new TracedFunctionCall()
                {
                    Name = Regex.Match(f, @"Function Called:\s(.+)\n").Groups[1].Value
                };

                var matches = Regex.Matches(f, @"\$Param\d+:\s(((?!(\$Param\d+:\s)|(Value:\s)|(-{32,}End))[\s\S])+)\n",
                    RegexOptions.Multiline);

                foreach (Match m in matches)
                    call.ParameterValues.Add(m.Groups[1].Value);

                Match valueMatch = Regex.Match(f, @"Value:\s(.+)\n");

                if (valueMatch.Success)
                    call.Value = valueMatch.Groups[1].Value;

                trace.Calls.Add(call);
            }

            return trace;
        }
        public void AddTrace(FileTrace Trace)
        {
            if (!Trace.Calls.Any())
                return;

            var page = Pages.SingleOrDefault(x => x.Page == Trace.File);

            if (page == null)
            {
                page = new ApplicationMapPage() { Page = Trace.File };

                Pages.Add(page);
            }

            foreach (var superglobal in Php.Superglobals)
            {
                var fields = page.SuperglobalNameCollectionTable[superglobal];
                var traceFields = Trace.Calls
                    .Where(x => x.ParameterValues.Any() && x.Name == superglobal && !fields.Contains(x.ParameterValues[0]))
                    .Select(x => x.ParameterValues[0]);

                if (!traceFields.Any())
                    continue;

                fields.AddRange(traceFields);
            }
        }
        public static FileTrace Parse(StreamReader Reader)
        {
            var trace = new FileTrace();
            var Text  = Reader.ReadToEnd();

            trace.RawText = Text;

            var functions = Text.Split(new string[]
            {
                "--------------------------------Start\n",
                "--------------------------------End\n",
            }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var f in functions)
            {
                var call = new TracedFunctionCall()
                {
                    Name = Regex.Match(f, @"Function Called:\s(.+)\n").Groups[1].Value
                };

                var matches = Regex.Matches(f, @"\$Param\d+:\s(((?!(\$Param\d+:\s)|(Value:\s)|(-{32,}End))[\s\S])+)\n",
                                            RegexOptions.Multiline);

                foreach (Match m in matches)
                {
                    call.ParameterValues.Add(m.Groups[1].Value);
                }

                Match valueMatch = Regex.Match(f, @"Value:\s(.+)\n");

                if (valueMatch.Success)
                {
                    call.Value = valueMatch.Groups[1].Value;
                }

                trace.Calls.Add(call);
            }

            return(trace);
        }
示例#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")));
            }
        }
示例#6
0
 public ScanAlert(ScanAlertOptions AlertType, string AlertName, FileTrace Trace)
 {
     _alertType = AlertType;
     _alertName = AlertName;
     _trace     = Trace;
 }
 public ScanAlert(ScanAlertOptions AlertType, string AlertName, FileTrace Trace)
 {
     _alertType = AlertType;
     _alertName = AlertName;
     _trace = Trace;
 }
示例#8
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")));
            }
        }