private void ParseAndAnalyze(string php, IVulnerabilityStorage storage) { FunctionsHandler fh = new FunctionsHandler(Config.FuncSpecSettings); fh.LoadJsonSpecifications(); var extractedFuncs = PHPParseUtils.ParseAndIterate <ClassAndFunctionExtractor>(php, Config.PHPSettings.PHPParserPath).Functions; fh.CustomFunctions.AddRange(extractedFuncs); var cfg = PHPParseUtils.ParseAndIterate <CFGCreator>(php, Config.PHPSettings.PHPParserPath).Graph; var incResolver = new IncludeResolver(new List <File>()); var fileStack = new Stack <File>(); fileStack.Push(new File() { FullPath = @"C:\TestFile.txt" }); var condAnalyser = new ConditionTaintAnalyser(AnalysisScope.File, incResolver, fileStack, fh); var funcMock = new Mock <Func <ImmutableVariableStorage, IIncludeResolver, AnalysisScope, AnalysisStacks, ImmutableVariableStorage> >(); var blockAnalyzer = new TaintBlockAnalyzer(storage, incResolver, AnalysisScope.File, funcMock.Object, new AnalysisStacks(fileStack), new FunctionAndMethodAnalyzerFactory(), fh); var immutableInitialTaint = new DefaultTaintProvider().GetTaint(); var cfgTaintAnalysis = new TaintAnalysis(blockAnalyzer, condAnalyser, immutableInitialTaint); var taintAnalysis = new CFGTraverser(new ForwardTraversal(), cfgTaintAnalysis, new QueueWorklist()); taintAnalysis.Analyze(cfg); }
/// <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, _funcHandler); blockAnalyzer.AnalysisExtensions.AddRange(AnalysisExtensions); var condAnalyser = new ConditionTaintAnalyser(AnalysisScope.Function, resolver, stacks.IncludeStack, _funcHandler); 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); }
public void IfElseVarDefTest() { const string php = @"<?php if(true) { $var = 1; } else { $var = 2; } $var = 3;"; var cfgCreator = ParseAndBuildCFG(php); var reachDef = new ReachingDefinitionAnalysis(); var analysis = new CFGTraverser(new ForwardTraversal(), reachDef, new QueueWorklist()); analysis.Analyze(cfgCreator.Graph); var inLineNumbers = new List <int>() { 4, 8 }; var outLineNumbers = new List <int>() { 4, 8, 10 }; foreach (var block in reachDef.ReachingSetDictionary) { if (block.Key.AstEntryNode != null && block.Key.AstEntryNode.Name == "node:Expr_Assign") { if (block.Value.DefinedInVars.Any()) { int ins = AstNode.GetStartLine(block.Value.DefinedInVars.Values.First().Info.Block.AstEntryNode); inLineNumbers.RemoveAll(x => ins == x); } if (block.Value.DefinedOutVars.Any()) { int outs = AstNode.GetStartLine(block.Value.DefinedOutVars.Values.First().Info.Block.AstEntryNode); outLineNumbers.RemoveAll(x => x == outs); } } } Assert.IsTrue(inLineNumbers.IsEmpty(), "The InLineNumbers are incorrect!"); Assert.IsTrue(outLineNumbers.IsEmpty(), "The OutLineNumbers are incorrect!"); }
private void AssertNoOfVulnsInMultipleCodeFiles(Tuple <string, string>[] codeFiles, int numberOfVulns) { FunctionsHandler fh = new FunctionsHandler(Config.FuncSpecSettings); fh.LoadJsonSpecifications(); 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(), fh); var condAnalyser = new ConditionTaintAnalyser(scope, inclResolver, stacks.IncludeStack, fh); 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)); }
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, _funcHandler); 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, _funcHandler); blockAnalyzer.AnalysisExtensions.AddRange(_components.BlockAnalyzers); var condAnalyser = new ConditionTaintAnalyser(scope, inclResolver, stacks.IncludeStack, _funcHandler); 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. ", _funcHandler.ScannedFunctions.Count, _funcHandler.CustomFunctions.Count, _funcHandler); 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); }