public FunctionAndMethodAnalyzer Create(ImmutableVariableStorage variableStorage, IIncludeResolver incResolver, AnalysisStacks stacks, CustomFunctionHandler customFuncHandler, IVulnerabilityStorage vulnerabilityStorage) { return new FunctionAndMethodAnalyzer(variableStorage, incResolver, stacks, customFuncHandler, vulnerabilityStorage) { UseSummaries = this.UseSummaries }; }
private ExpressionInfo Node_FuncCall(XmlNode node) { var functionCallExtractor = new FunctionCallExtractor(); var functionCall = functionCallExtractor.ExtractFunctionCall(node); bool isAlreadyInStack = _analysisStacks.CallStack.Any(x => x.Name == functionCall.Name); _analysisStacks.CallStack.Push(functionCall); var argInfos = new List<ExpressionInfo>(); //Actually extract the arguments for (uint index = 1; index <= functionCall.Arguments.Count; index++) { var item = functionCall.Arguments.FirstOrDefault(x => x.Key == index); var exprInfo = this.Analyze(item.Value); if (_varResolver.IsResolvableNode(item.Value)) { var variableResolveResult = _varResolver.ResolveVariable(item.Value); exprInfo.ValueInfo = variableResolveResult.Variable.Info; } argInfos.Add(exprInfo); } if (functionCall.Name == "") { var expr_info = new ExpressionInfo(); _analysisStacks.CallStack.Pop(); return argInfos.Aggregate(expr_info, (current, info) => current.Merge(info)); } var customFunctionHandler = new CustomFunctionHandler(this._analyzer, _subroutineAnalyzerFactory); customFunctionHandler.AnalysisExtensions.AddRange(this.AnalysisExtensions); var immutableVariableStorage = ImmutableVariableStorage.CreateFromMutable(_variableStorage); var functionMethodAnalyzer = this._subroutineAnalyzerFactory.Create(immutableVariableStorage, _inclusionResolver, _analysisStacks, customFunctionHandler, _vulnerabilityStorage); var resultTaintSet = new ExpressionInfo(); if (!isAlreadyInStack) { resultTaintSet = functionMethodAnalyzer.AnalyzeFunctionCall(functionCall, argInfos); } FunctionsHandler fh = FunctionsHandler.Instance; var sqlSaniFunc = fh.FindSQLSanitizerByName(functionCall.Name); var sqlSinkFunc = fh.FindSQLSinkByName(functionCall.Name); var xssSaniFunc = fh.FindXSSSanitizerByName(functionCall.Name); var xssSinkFunc = fh.FindXSSSinkByName(functionCall.Name); if(sqlSaniFunc != null && sqlSaniFunc.DefaultStatus == SQLITaint.None) { resultTaintSet.ExpressionTaint.SqliTaint.Clear(); resultTaintSet.ValueInfo.Taints.SqliTaint.Clear(); resultTaintSet.ExpressionStoredTaint.Taint.SqliTaint.Clear(); } if (xssSaniFunc != null && xssSaniFunc.DefaultStatus == XSSTaint.None) { resultTaintSet.ExpressionTaint.XssTaint.Clear(); resultTaintSet.ValueInfo.Taints.XssTaint.Clear(); resultTaintSet.ExpressionStoredTaint.Taint.XssTaint.Clear(); } if (sqlSinkFunc != null) { var vulnerableSqlParams = sqlSinkFunc.Parameters.Where(x => x.Value.IsSensitive).ToDictionary(pair => pair.Key); var param = functionCall.Arguments.Where(x => vulnerableSqlParams.Keys.Any(z => z.Item1 == x.Key)); foreach (var parameter in param) { var argInfo = argInfos.ElementAt((int) (parameter.Key - 1)); CheckForSQLVulnerabilities(argInfo, parameter.Value); } } if (xssSinkFunc != null) { var vulnerableXssParams = xssSinkFunc.Parameters.Where(x => x.Value.IsSensitive).ToDictionary(pair => pair.Key); var param = functionCall.Arguments.Where(x => vulnerableXssParams.Keys.Any(z => z.Item1 == x.Key)); foreach (var parameter in param) { var argInfo = argInfos.ElementAt((int)(parameter.Key - 1)); CheckForXssVulnerabilities(argInfo, parameter.Value); } } resultTaintSet = StoredFuncHandler(resultTaintSet, node, argInfos); var argumentInfoWithIndex = argInfos.Select((a, i) => new { Info = a, Index = (uint)i + 1 }) .ToDictionary(a => a.Index, a => a.Info); resultTaintSet = ApplyAnalysisExtensionsToFuncCall(node, resultTaintSet, argumentInfoWithIndex); _analysisStacks.CallStack.Pop(); return resultTaintSet; }
/// <summary> /// Calls AnalyzeFuncCall on all external components. This was created because we currently do not call Analyze on "Node:Arg", /// which is needed to let the components find the arguments themselves. /// TODO: Handle Node:Arg in the analysis explicitly, to allow this. /// </summary> private ExpressionInfo ApplyAnalysisExtensionsToFuncCall(XmlNode node, ExpressionInfo currentInfo, IDictionary<uint, ExpressionInfo> argInfos) { foreach (var analysisExtension in AnalysisExtensions) { analysisExtension.FunctionMethodAnalyzerFactory = storage => { var customFunctionHandler = new CustomFunctionHandler(this._analyzer, _subroutineAnalyzerFactory); customFunctionHandler.AnalysisExtensions.AddRange(this.AnalysisExtensions); var varStorage = ImmutableVariableStorage.CreateFromMutable(storage); return _subroutineAnalyzerFactory.Create(varStorage, _inclusionResolver, _analysisStacks, customFunctionHandler, _vulnerabilityStorage); }; currentInfo = analysisExtension.AnalyzeFunctionCall(node, currentInfo, _variableStorage, _vulnerabilityStorage, argInfos, this._analysisStacks); } return currentInfo; }
private ExpressionInfo Node_MethodCall(XmlNode node) { var functionCallExtractor = new FunctionCallExtractor(); var methodCall = functionCallExtractor.ExtractMethodCall(node, this._variableStorage, this._analysisScope); bool isAlreadyInStack = _analysisStacks.CallStack.Any(x => x.Name == methodCall.Name); _analysisStacks.CallStack.Push(methodCall); var argInfos = new List<ExpressionInfo>(); //Actually analyze the arguments for (uint index = 1; index <= methodCall.Arguments.Count; index++) { var item = methodCall.Arguments.FirstOrDefault(x => x.Key == index); var exprInfo = this.Analyze(item.Value); if (_varResolver.IsResolvableNode(item.Value)) { var @var = _varResolver.ResolveVariable(item.Value); exprInfo.ValueInfo = @var.Variable.Info; } argInfos.Add(exprInfo); } if (methodCall.Name == "") { var exprInfo = new ExpressionInfo(); _analysisStacks.CallStack.Pop(); return argInfos.Aggregate(exprInfo, (current, info) => current.Merge(info)); } var customFunctionHandler = new CustomFunctionHandler(this._analyzer, _subroutineAnalyzerFactory); customFunctionHandler.AnalysisExtensions.AddRange(this.AnalysisExtensions); var functionMethodAnalyzer = _subroutineAnalyzerFactory.Create(ImmutableVariableStorage.CreateFromMutable(_variableStorage), _inclusionResolver, _analysisStacks, customFunctionHandler, _vulnerabilityStorage); var methodCallTaintSet = new ExpressionInfo(); if(!isAlreadyInStack) { methodCallTaintSet = functionMethodAnalyzer.AnalyzeMethodCall(methodCall, argInfos); } FunctionsHandler fh = FunctionsHandler.Instance; var resultTaintSet = new ExpressionInfo(); foreach (var className in methodCall.ClassNames.Distinct()) { var tempResultTaintSet = methodCallTaintSet.AssignmentClone(); var sqlSaniFunc = fh.FindSQLSanitizerByName(methodCall.CreateFullMethodName(className)); var sqlSinkFunc = fh.FindSQLSinkByName(methodCall.CreateFullMethodName(className)); var xssSaniFunc = fh.FindXSSSanitizerByName(methodCall.CreateFullMethodName(className)); var xssSinkFunc = fh.FindXSSSinkByName(methodCall.CreateFullMethodName(className)); if (sqlSaniFunc != null && sqlSaniFunc.DefaultStatus == SQLITaint.None) { resultTaintSet.ExpressionTaint.SqliTaint.Clear(); } if (xssSaniFunc != null && xssSaniFunc.DefaultStatus == XSSTaint.None) { resultTaintSet.ExpressionTaint.XssTaint.Clear(); } if (sqlSinkFunc != null || xssSinkFunc != null) { if (sqlSinkFunc != null) { var vulnerableSqlParams = sqlSinkFunc.Parameters.Where(x => x.Value.IsSensitive) .ToDictionary(pair => pair.Key); var parameters = methodCall.Arguments.Where(x => vulnerableSqlParams.Keys.Any(z => z.Item1 == x.Key)); foreach (var parameter in parameters) { //var argInfo = Analyze(parameter.Value); var argInfo = argInfos.ElementAt((int)(parameter.Key - 1)); CheckForSQLVulnerabilities(argInfo, parameter.Value); } if (sqlSinkFunc.ReturnType == "object" || sqlSinkFunc.ReturnType == "mix") { resultTaintSet.ValueInfo.ClassNames.AddRange(sqlSinkFunc.Classnames); } } if (xssSinkFunc != null) { var vulnerableXssParams = xssSinkFunc.Parameters.Where(x => x.Value.IsSensitive).ToDictionary(pair => pair.Key); var param = methodCall.Arguments.Where(x => vulnerableXssParams.Keys.Any(z => z.Item1 == x.Key)); foreach (var parameter in param) { var argInfo = argInfos.ElementAt((int)(parameter.Key - 1)); CheckForXssVulnerabilities(argInfo, parameter.Value); } } // Assuming sinks does not return taint. resultTaintSet.ExpressionTaint.ClearTaint(); resultTaintSet.ExpressionStoredTaint.Taint.ClearTaint(); } tempResultTaintSet = StoredMethodHandler(tempResultTaintSet, node); resultTaintSet = resultTaintSet.Merge(tempResultTaintSet); var methodNameWithClass = methodCall.CreateFullMethodName(className); bool isStoredProvider = FunctionsHandler.Instance.FindStoredProviderMethods(methodNameWithClass).Any(); if (isStoredProvider) { resultTaintSet.ExpressionStoredTaint = resultTaintSet.ExpressionStoredTaint.Merge(methodCall.Var.Info.PossibleStoredTaint); //TODO: The following is not true in all cases. // What cases? var cloned = resultTaintSet.ExpressionStoredTaint.Taint.DeepClone(); resultTaintSet.ValueInfo.NestedVariablePossibleStoredDefaultTaintFactory = () => cloned; } } _analysisStacks.CallStack.Pop(); return resultTaintSet; }