public FunctionAndMethodAnalyzer Create(ImmutableVariableStorage variableStorage, IIncludeResolver incResolver,
     AnalysisStacks stacks, CustomFunctionHandler customFuncHandler,
     IVulnerabilityStorage vulnerabilityStorage)
 {
     return new FunctionAndMethodAnalyzer(variableStorage, incResolver, stacks, customFuncHandler, vulnerabilityStorage)
            {
                UseSummaries = this.UseSummaries
            };
 }
Example #2
0
 public ExpressionInfo AnalyzeFunctionCall(XmlNode node, ExpressionInfo exprInfo, IVariableStorage varStorage, 
                                           IVulnerabilityStorage vulnStorage, IDictionary<uint, ExpressionInfo> argumentInfos, AnalysisStacks analysisStacks)
 {
     var funcCall = new FunctionCallExtractor().ExtractFunctionCall(node);
     if (_getOptionsFunctions.Contains(funcCall.Name) ||
         _addOptionFunctions.Contains(funcCall.Name) ||
         _updateOptionFunctions.Contains(funcCall.Name))
     {
         return HandleOptionsCall(funcCall, node, exprInfo, varStorage, vulnStorage, argumentInfos, analysisStacks);
     }
     else if (_hookFunctions.Contains(funcCall.Name))
     {
         return HandleHookCall(node, exprInfo, varStorage, analysisStacks);
     }
     return exprInfo;
 }
Example #3
0
        /// <summary>
        /// Analyses a custom function in for security issues, with the currenctly known taint for actual parameters.
        /// </summary>
        /// <returns>A TainSets for the custom function that is being analyzed</returns>
        /// <param name="customFunction">Custom function object to perform the analysis on</param>
        /// <param name="varStorage">The currently known variable storage (this is to included because of superglobals, globals etc.)</param>
        /// <param name="paramActualVals">Parameter actual values</param>
        /// <param name="resolver">File inclusion resolver</param>
        /// <param name="includeStack">Currently known includes</param>
        /// <param name="functionCalls">Currently known function calls</param>
        internal ExpressionInfo AnalyseCustomFunction(Function customFunction, ImmutableVariableStorage varStorage, IVulnerabilityStorage vulnerabilityStorage,
            IList<ExpressionInfo> paramActualVals, IIncludeResolver resolver, AnalysisStacks stacks)
        {
            var stmts = customFunction.AstNode.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Stmts).FirstChild;

            var traverser = new XmlTraverser();
            var cfgcreator = new CFGCreator();
            traverser.AddVisitor(cfgcreator);
            traverser.Traverse(stmts);

            var cfgPruner = new CFGPruner();
            cfgPruner.Prune(cfgcreator.Graph);

            var initialTaint = varStorage.ToMutable();
            initialTaint.SuperGlobals.Clear();
            initialTaint.SuperGlobals.AddRange(varStorage.SuperGlobals);
            initialTaint.LocalVariables.Clear();
            initialTaint.LocalAccessibleGlobals.Clear();

            for(int i = 1; i <= paramActualVals.Count; i++)
            {
                var paramFormal = customFunction.Parameters.FirstOrDefault(x => x.Key.Item1 == i);
                if (paramFormal.Value == null)
                {
                    continue;
                }
                var @var = new Variable(paramFormal.Value.Name, VariableScope.Function) {Info = paramActualVals[i - 1].ValueInfo};
                initialTaint.LocalVariables.Add(paramFormal.Value.Name, @var);
            }

            var blockAnalyzer = new TaintBlockAnalyzer(vulnerabilityStorage, resolver, AnalysisScope.Function, fileAnalyzer, stacks, subroutineAnalyzerFactory);
            blockAnalyzer.AnalysisExtensions.AddRange(AnalysisExtensions);
            var condAnalyser = new ConditionTaintAnalyser(AnalysisScope.Function, resolver, stacks.IncludeStack);
            var cfgTaintAnalysis = new TaintAnalysis(blockAnalyzer, condAnalyser, ImmutableVariableStorage.CreateFromMutable(initialTaint));
            //var taintAnalysis = new CFGTraverser(new ForwardTraversal(), cfgTaintAnalysis, new QueueWorklist());
            var taintAnalysis = new CFGTraverser(new ForwardTraversal(), cfgTaintAnalysis, new ReversePostOrderWorkList(cfgcreator.Graph));
            taintAnalysis.Analyze(cfgcreator.Graph);

            var exprInfoAll = new ExpressionInfo();

            foreach (ExpressionInfo exprInfo in blockAnalyzer.ReturnInfos)
            {
                exprInfoAll = exprInfoAll.Merge(exprInfo);
            }

            return exprInfoAll;
        }
Example #4
0
        public TaintBlockAnalyzer(IVulnerabilityStorage vulnerabilityStorage, IIncludeResolver inclusionResolver, AnalysisScope scope,
            Func<ImmutableVariableStorage, IIncludeResolver, AnalysisScope, AnalysisStacks, ImmutableVariableStorage> analyzeTaint, 
            AnalysisStacks stacks, FunctionAndMethodAnalyzerFactory subroutineAnalyzerFactory)
            : this()
        {
            Preconditions.NotNull(vulnerabilityStorage, "vulnerabilityStorage");
            Preconditions.NotNull(inclusionResolver, "inclusionResolver");
            Preconditions.NotNull(analyzeTaint, "analyzeTaint");
            Preconditions.NotNull(stacks, "stacks");
            Preconditions.NotNull(subroutineAnalyzerFactory, "subroutineAnalyzerFactory");

            this._vulnerabilityStorage = vulnerabilityStorage;
            this._inclusionResolver = inclusionResolver;
            this._analyzer = analyzeTaint;
            this._analysisScope = scope;
            this.ReturnInfos = new List<ExpressionInfo>();
            this._analysisStacks = stacks;
            this._subroutineAnalyzerFactory = subroutineAnalyzerFactory;
        }
Example #5
0
        private ExpressionInfo HandleUpdateAddOptions(FunctionCall call, ExpressionInfo exprInfo, IVulnerabilityStorage storage, 
                                                      IDictionary<uint, ExpressionInfo> argumentInfos, AnalysisStacks analysisStacks)
        {
            XmlNode firstArgument;
            XmlNode secondArgument;

            string optionKeyValue;

            if (call.Arguments.TryGetValue(1, out firstArgument) &&
                call.Arguments.TryGetValue(2, out secondArgument) &&
                TryGetOptionKeyValue(firstArgument, argumentInfos[1], out optionKeyValue))
            {
                foreach (var sqliTaintSet in argumentInfos.ElementAt(1).Value.ExpressionTaint.SqliTaint)
                {
                    if (sqliTaintSet.TaintTag == SQLITaint.None)
                    {
                        continue;
                    }
                    string varName = (sqliTaintSet.InitialTaintedVariable ?? "???");
                    string message = "Stored SQLI found - Ingoing: " + varName +
                                    " on line: " + call.StartLine + " in file: " + analysisStacks.IncludeStack.Peek();

                    storage.AddPossibleStoredVulnerability(new StoredVulnerabilityInfo()
                    {
                        IncludeStack = analysisStacks.IncludeStack.ToImmutableStack(),
                        CallStack = analysisStacks.CallStack.ToImmutableStack(),
                        Message = message,
                        VulnerabilityType = VulnType.SQL,
                        PossibleStoredVuln = new StoredVulnInfo()
                                             {
                                                 ICantFeelIt = IsItInYet.YesItsGoingIn,
                                                 StorageName = optionKeyValue,
                                                 StorageOrigin = "Options",
                                                 Taint = new TaintSets(sqliTaintSet, new XSSTaintSet())
                                             }
                    });
                }
                foreach (var xssTaintSet in argumentInfos.ElementAt(1).Value.ExpressionTaint.XssTaint)
                {
                    if (xssTaintSet.TaintTag == XSSTaint.None)
                    {
                        continue;
                    }
                    string varName = (xssTaintSet.InitialTaintedVariable ?? "???");
                    string message = "Stored XSS found - Ingoing: " + varName +
                                    " on line: " + call.StartLine + " in file: " + analysisStacks.IncludeStack.Peek();

                    storage.AddPossibleStoredVulnerability(new StoredVulnerabilityInfo()
                    {
                        IncludeStack = analysisStacks.IncludeStack.ToImmutableStack(),
                        CallStack = analysisStacks.CallStack.ToImmutableStack(),
                        Message = message,
                        VulnerabilityType = VulnType.XSS,
                        PossibleStoredVuln = new StoredVulnInfo()
                                            {
                                                ICantFeelIt = IsItInYet.YesItsGoingIn,
                                                StorageName = optionKeyValue,
                                                StorageOrigin = "Options",
                                                Taint = new TaintSets(new SQLITaintSet(), xssTaintSet)
                                            }
                    });
                }
            }

            return exprInfo;
        }
Example #6
0
        private ExpressionInfo HandleOptionsCall(FunctionCall call, XmlNode node, ExpressionInfo exprInfo, IVariableStorage currentStorage, 
                                                 IVulnerabilityStorage storage, IDictionary<uint, ExpressionInfo> argumentInfos, AnalysisStacks analysisStacks)
        {
            if (_getOptionsFunctions.Contains(call.Name))
            {
                return HandleGetOptions(call, argumentInfos, exprInfo);
            }
            else if (_updateOptionFunctions.Contains(call.Name) ||
                     _addOptionFunctions.Contains(call.Name))
            {
                return HandleUpdateAddOptions(call, exprInfo, storage, argumentInfos, analysisStacks);
            }

            return exprInfo;
        }
Example #7
0
        /// <summary>
        /// Make sure that hardcoded callback functions are analyzed.
        /// </summary>
        private ExpressionInfo HandleHookCall(XmlNode node, ExpressionInfo exprInfo, IVariableStorage currentStorage, AnalysisStacks analysisStacks)
        {
            var functionCall = new FunctionCallExtractor().ExtractFunctionCall(node);
            var result = new ExpressionInfo();

            foreach (var argument in functionCall.Arguments.Where(a => a.Value.LocalName == AstConstants.Nodes.Scalar_String))
            {
                var stringValue = ScalarNode.GetStringValue(argument.Value);
                var functions = FunctionsHandler.Instance.LookupFunction(stringValue);
                if (functions.Any())
                {
                    //Console.WriteLine("FOUND " + functions.Count() + " functions with name: " + stringValue);
                    var functionAnalyzer = this.FunctionMethodAnalyzerFactory(currentStorage);
                    var call = new FunctionCall(stringValue, null, AstNode.GetStartLine(node), AstNode.GetEndLine(node));

                    if (analysisStacks.CallStack.Any(c => c.Name == call.Name))
                    {
                        // Avoid recursive registrations.
                        continue;
                    }
                    analysisStacks.CallStack.Push(call);
                    var funcCallResult = functionAnalyzer.AnalyzeFunctionCall(call, new ExpressionInfo[0]);
                    analysisStacks.CallStack.Pop();

                    result = result.Merge(funcCallResult);
                }

                // https://codex.wordpress.org/Function_Reference/add_submenu_page
                // If a method is called, it is called with: array( $this, 'function_name' ) or array( __CLASS__, 'function_name' )

            }
            return result;
        }
Example #8
0
        private void AssertNoOfVulnsInMultipleCodeFiles(Tuple<string, string>[] codeFiles, int numberOfVulns)
        {
            var vulnStorage = new Mock<IVulnerabilityStorage>();

            var parsedFiles = codeFiles.Select(code => new File(PHPParseUtils.ParsePHPCode(code.Item2, Config.PHPSettings.PHPParserPath)) 
                                                       {
                                                            FullPath = code.Item1,
                                                            CFG =  PHPParseUtils.ParseAndIterate<CFGCreator>(code.Item2, Config.PHPSettings.PHPParserPath).Graph
                                                       }).ToArray();

            Func<ImmutableVariableStorage, IIncludeResolver, AnalysisScope, AnalysisStacks, ImmutableVariableStorage> fileTaintAnalyzer = null;
            fileTaintAnalyzer = (varStorage, inclResolver, scope, stacks) =>
            {
                Preconditions.NotNull(varStorage, "varStorage");
                Preconditions.NotNull(inclResolver, "inclResolver");
                var fileToAnalyze = stacks.IncludeStack.Peek();
                var blockAnalyzer = new TaintBlockAnalyzer(vulnStorage.Object, inclResolver, scope, fileTaintAnalyzer, stacks, new FunctionAndMethodAnalyzerFactory());
                var condAnalyser = new ConditionTaintAnalyser(scope, inclResolver, stacks.IncludeStack);
                var cfgTaintAnalysis = new PHPAnalysis.Analysis.CFG.TaintAnalysis(blockAnalyzer, condAnalyser, varStorage);
                var analyzer = new CFGTraverser(new ForwardTraversal(), cfgTaintAnalysis, new ReversePostOrderWorkList(fileToAnalyze.CFG));
                
                analyzer.Analyze(fileToAnalyze.CFG);
                return cfgTaintAnalysis.Taints[fileToAnalyze.CFG.Vertices.Single(block => block.IsLeaf)].Out[EdgeType.Normal];
            };

            foreach (var file in parsedFiles)
            {
                var inclusionResolver = new IncludeResolver(parsedFiles);
                var fileStack = new Stack<File>();
                fileStack.Push(file);
                var immutableInitialTaint = new DefaultTaintProvider().GetTaint();

                var stacks = new AnalysisStacks(fileStack);
                fileTaintAnalyzer(immutableInitialTaint, inclusionResolver, AnalysisScope.File, stacks);
            }

            vulnStorage.Verify(x => x.AddVulnerability(It.IsAny<IVulnerabilityInfo>()), Times.Exactly(numberOfVulns));
        }
Example #9
0
        private static void Analyze(Arguments arguments, Config configuration)
        {
            Console.WriteLine("Parsing project at: " + arguments.Target);
            Console.WriteLine();

            foreach (var analysisStartingListener in _components.AnalysisStartingListeners)
            {
                // TODO - This should probably be a proper event - same goes for EndingEvent (this will also remove the loop(s)).
                analysisStartingListener.AnalysisStarting(null, new AnalysisStartingEventArgs(configuration, arguments));
            }

            var stopwatch = Stopwatch.StartNew();

            Console.WriteLine("Building ASTs..");
            ParseResult parseResult = ParseTarget(arguments, configuration);

            Console.WriteLine(" - AST build for {0} files ({1} failed)..", parseResult.ParsedFiles.Count, parseResult.FilesThatFailedToParse.Count);
            Console.WriteLine("Traversing ASTs..");

            var filesCollection = new List<File>();
            var runningVulnReporter = new CompositeVulneribilityReporter(_components.VulnerabilityReporters);
            var vulnerabilityStorage = new ReportingVulnerabilityStorage(runningVulnReporter);

            var progrssIndicator = ProgressIndicatorFactory.CreateProgressIndicator(parseResult.ParsedFiles.Count());
            foreach (var parsedFile in parseResult.ParsedFiles)
            {
                progrssIndicator.Step();

                var file = BuildFileCFGAndExtractFileInformation(parsedFile);
                filesCollection.Add(file);
            }

            var subroutineAnalyzerFactory = new FunctionAndMethodAnalyzerFactory { UseSummaries = arguments.UseFunctionSummaries };
            Func<ImmutableVariableStorage, IIncludeResolver, AnalysisScope, AnalysisStacks,
                 ImmutableVariableStorage> fileTaintAnalyzer = null;
            fileTaintAnalyzer = (varStorage, inclResolver, scope, stacks) =>
            {
                Preconditions.NotNull(varStorage, "varStorage");
                Preconditions.NotNull(inclResolver, "inclResolver");

                var blockAnalyzer = new TaintBlockAnalyzer(vulnerabilityStorage, inclResolver, scope, fileTaintAnalyzer, stacks, subroutineAnalyzerFactory);
                blockAnalyzer.AnalysisExtensions.AddRange(_components.BlockAnalyzers);
                var condAnalyser = new ConditionTaintAnalyser(scope, inclResolver, stacks.IncludeStack);
                var cfgTaintAnalysis = new TaintAnalysis(blockAnalyzer, condAnalyser, varStorage);
                var fileToAnalyze = stacks.IncludeStack.Peek();
                var analyzer = new CFGTraverser(new ForwardTraversal(), cfgTaintAnalysis, new ReversePostOrderWorkList(fileToAnalyze.CFG));
                //var analyzer = new CFGTraverser(new ForwardTraversal(), cfgTaintAnalysis, new QueueWorklist());
                analyzer.Analyze(fileToAnalyze.CFG);
                return cfgTaintAnalysis.Taints[fileToAnalyze.CFG.Vertices.Single(block => block.IsLeaf)].Out[EdgeType.Normal];
            };

            foreach (var file in filesCollection)
            {
                Console.WriteLine(Environment.NewLine + "=============================");
                Console.WriteLine("Analyzing {0}..", file.FullPath);
                var initialTaint = GetDefaultTaint();
                var inclusionResolver = new IncludeResolver(filesCollection);

                var stacks = new AnalysisStacks(file);
                fileTaintAnalyzer(initialTaint, inclusionResolver, AnalysisScope.File, stacks);
            }

            Console.WriteLine("Scanned {0}/{1} subroutines. ", FunctionsHandler.Instance.ScannedFunctions.Count, FunctionsHandler.Instance.CustomFunctions.Count);

            if (arguments.ScanAllSubroutines)
            {
                Console.WriteLine("Scanning remaining subroutines..");
                ScanUnscannedSubroutines(filesCollection, fileTaintAnalyzer, subroutineAnalyzerFactory, vulnerabilityStorage);
            }

            vulnerabilityStorage.CheckForStoredVulnerabilities();
            //parseResult.ParsedFiles.Values.First().Save(@"C:\Users\Kenneth\Documents\Uni\TestScript\current\parsedFile");

            stopwatch.Stop();

            foreach (var analysisEndedListener in _components.AnalysisEndedListeners)
            {
                analysisEndedListener.AnalysisEnding(null, new AnalysisEndedEventArgs(stopwatch.Elapsed));
            }

            Console.WriteLine("Time spent: " + stopwatch.Elapsed);
            Console.WriteLine("Found {0} vulnerabilities.", runningVulnReporter.NumberOfReportedVulnerabilities);
        }
Example #10
0
        private static void ScanUnscannedSubroutines(List<File> filesCollection, Func<ImmutableVariableStorage, IIncludeResolver, AnalysisScope, AnalysisStacks, ImmutableVariableStorage> fileTaintAnalyzer, FunctionAndMethodAnalyzerFactory subroutineAnalyzerFactory, ReportingVulnerabilityStorage vulnerabilityStorage)
        {
            var defaultTaint = new DefaultTaintProvider().GetTaint();

            foreach (var file in filesCollection)
            {
                var analysisStacks = new AnalysisStacks(file);
                var analyser = new FunctionAndMethodAnalyzer(defaultTaint,
                    new IncludeResolver(filesCollection), analysisStacks,
                    new CustomFunctionHandler(fileTaintAnalyzer, subroutineAnalyzerFactory), vulnerabilityStorage);

                foreach (var function in file.Functions.SelectMany(f => f.Value).Except(FunctionsHandler.Instance.ScannedFunctions))
                {
                    var functionCall = new FunctionCall(function.Name, function.AstNode, 0, 0);
                    analysisStacks.CallStack.Push(functionCall);

                    analyser.AnalyzeFunctionCall(functionCall, new List<ExpressionInfo>());
                }
                foreach (var @class in file.Classes.SelectMany(c => c.Value))
                {
                    foreach (var method in @class.Methods.Except(FunctionsHandler.Instance.ScannedFunctions))
                    {
                        var methodCall = new MethodCall(method.Name, new [] { @class.Name }, method.AstNode, 0, 0);
                        analysisStacks.CallStack.Push(methodCall);

                        analyser.AnalyzeMethodCall(methodCall, new List<ExpressionInfo>());
                    }
                }
            }
        }