public bool IsVulnerable(SemanticModel model, AssignmentExpressionSyntax syntax, DiagnosticId ruleId) { var leftSyntax = syntax?.Left as MemberAccessExpressionSyntax; if (leftSyntax == null) { return(false); } if (string.Compare(leftSyntax.Name.Identifier.ValueText, "Path", StringComparison.OrdinalIgnoreCase) != 0) { return(false); } var leftSymbol = model.GetSymbolInfo(leftSyntax).Symbol; if (leftSymbol == null) { return(false); } if (!leftSymbol.ToString().StartsWith("System.DirectoryServices.DirectoryEntry")) { return(false); } var expressionAnalyzer = SyntaxNodeAnalyzerFactory.Create(syntax.Right); if (expressionAnalyzer.CanIgnore(model, syntax.Right)) { return(false); } if (expressionAnalyzer.CanSuppress(model, syntax.Right, ruleId)) { return(false); } return(true); }
public bool IsVulnerable(SemanticModel model, ObjectCreationExpressionSyntax syntax, DiagnosticId ruleId) { if (!containsCommands(syntax)) { return(false); } var symbol = model.GetSymbolInfo(syntax).Symbol as IMethodSymbol; if (!isConstructor(symbol)) { return(false); } if (syntax.ArgumentList.Arguments.Count == 0) { return(false); } var arg = syntax.ArgumentList.Arguments[0].Expression; //var argSyntax = arg.Expression; var expressionAnalyzer = SyntaxNodeAnalyzerFactory.Create(arg); if (expressionAnalyzer.CanIgnore(model, arg)) { return(false); } if (expressionAnalyzer.CanSuppress(model, arg, ruleId)) { return(false); } Source = arg; return(true); }
public bool IsVulnerable(SemanticModel model, ObjectCreationExpressionSyntax syntax, DiagnosticId ruleId) { //Cheap check for class name if (!syntax.ToString().Contains("DirectorySearcher")) { return(false); } //Verify full namespace var symbol = model.GetSymbolInfo(syntax).Symbol as IMethodSymbol; if (!symbol.IsCtorFor("System.DirectoryServices.DirectorySearcher")) { return(false); } //Bail if no initializers or arguments to analyze if (syntax.Initializer?.Expressions.Count == 0 && syntax.ArgumentList?.Arguments.Count == 0) { return(false); } //Option 1: Check the initializers for the "Filter" property if (syntax.Initializer?.Expressions.Count > 0) { var filter = syntax.Initializer?.Expressions.OfType <AssignmentExpressionSyntax>() .FirstOrDefault(p => (p.Left as IdentifierNameSyntax)?.Identifier.ValueText == "Filter"); if (filter != null) { var expressionAnalyzer = SyntaxNodeAnalyzerFactory.Create(filter.Right); if (expressionAnalyzer.CanIgnore(model, filter.Right)) { return(false); } if (expressionAnalyzer.CanSuppress(model, filter.Right, ruleId)) { return(false); } //Right expression needs more analysis in DFA Source = filter.Right; return(true); } return(false); } //Option 2: Check the argument list for the "filter" parameter if (syntax.ArgumentList?.Arguments.Count > 0) { //This is a bitch because overloads send the "filter" in different parameter positions //public DirectorySearcher(string filter) //public DirectorySearcher(string filter, string[] propertiesToLoad) //public DirectorySearcher(DirectoryEntry searchRoot, string filter, string[] propertiesToLoad) //public DirectorySearcher(string filter, string[] propertiesToLoad, SearchScope scope) //public DirectorySearcher(DirectoryEntry searchRoot, string filter, string[] propertiesToLoad, SearchScope scope) //Solution: Check the 2st parameter first, this is always filter. //If not, check the 1st parm and see if it's a DirectoryEntry object, if not its the filter ExpressionSyntax expressionSyntax = null; if (syntax.ArgumentList?.Arguments.Count > 1) { expressionSyntax = syntax.ArgumentList?.Arguments[1].Expression; } else { expressionSyntax = syntax.ArgumentList?.Arguments[0].Expression; //Quick symbol check to weed out directory entry objects in parm 0 position var expressionSymbol = model.GetSymbolInfo(expressionSyntax).Symbol as ISymbol; //Weed out directory entry objects if (expressionSymbol != null && expressionSymbol.OriginalDefinition != null && expressionSymbol.OriginalDefinition.ToString().StartsWith("System.DirectoryServices.DirectoryEntry")) { expressionSyntax = null; } //Weed out local objects that are base directory entry var localExpressionSymbol = expressionSymbol as ILocalSymbol; if (localExpressionSymbol?.Type.ToString() == "System.DirectoryServices.DirectoryEntry") { expressionSyntax = null; } } //If no string expression syntax type, bail out if (expressionSyntax == null) { return(false); } //Cheap checks for suppression before registering for DFA var expressionAnalyzer = SyntaxNodeAnalyzerFactory.Create(expressionSyntax); if (expressionAnalyzer.CanIgnore(model, expressionSyntax)) { return(false); } if (expressionAnalyzer.CanSuppress(model, expressionSyntax, ruleId)) { return(false); } //Filter param needs more advanced analysis Source = expressionSyntax; return(true); } return(false); }
public bool IsVulnerable(SemanticModel model, ObjectCreationExpressionSyntax syntax, DiagnosticId ruleId) { //These persist from previous invocations (clear before staring) //TODO: Make this lock during execution until we call ToImmutableArray() after this is done this.Sources.Clear(); //Cheap check for class & method name if (!ContainsTypeName(syntax)) { return(false); } //If we found it, verify the namespace var symbol = model.GetSymbolInfo(syntax).Symbol; if (!IsType(symbol)) { return(false); } //Bail if no initializers or arguments to analyze if (syntax.Initializer?.Expressions.Count == 0 && syntax.ArgumentList?.Arguments.Count == 0) { return(false); } //Constructor options // 0 parms passes onto the assignment expression analyzer // 1 param (filename) // 2 param (filename, arguments) if (syntax.ArgumentList?.Arguments.Count > 0) { //File name parameter checks var fileNameSyntax = syntax.ArgumentList.Arguments[0].Expression; var expressionAnalyzer = SyntaxNodeAnalyzerFactory.Create(fileNameSyntax); if (!expressionAnalyzer.CanIgnore(model, fileNameSyntax) && !expressionAnalyzer.CanSuppress(model, fileNameSyntax, ruleId)) { this.Sources.Add(fileNameSyntax); } //Arguments parameter checks if (syntax.ArgumentList?.Arguments.Count > 1) { var argumenetSyntax = syntax.ArgumentList.Arguments[1].Expression; expressionAnalyzer = SyntaxNodeAnalyzerFactory.Create(argumenetSyntax); if (!expressionAnalyzer.CanIgnore(model, argumenetSyntax) && !expressionAnalyzer.CanSuppress(model, argumenetSyntax, ruleId)) { this.Sources.Add(argumenetSyntax); } } } //Bail if no initializers or arguments to analyze if (syntax.Initializer?.Expressions.Count > 0) { var filter = syntax.Initializer?.Expressions.OfType <AssignmentExpressionSyntax>() .FirstOrDefault(p => (p.Left as IdentifierNameSyntax)?.Identifier.ValueText == "FileName"); if (filter != null) { var expressionAnalyzer = SyntaxNodeAnalyzerFactory.Create(filter.Right); if (!expressionAnalyzer.CanIgnore(model, filter.Right) && !expressionAnalyzer.CanSuppress(model, filter.Right, ruleId)) { this.Sources.Add(filter.Right); } } filter = syntax.Initializer?.Expressions.OfType <AssignmentExpressionSyntax>() .FirstOrDefault(p => (p.Left as IdentifierNameSyntax)?.Identifier.ValueText == "Arguments"); if (filter != null) { var expressionAnalyzer = SyntaxNodeAnalyzerFactory.Create(filter.Right); if (!expressionAnalyzer.CanIgnore(model, filter.Right) && !expressionAnalyzer.CanSuppress(model, filter.Right, ruleId)) { this.Sources.Add(filter.Right); } } } return(this.Sources != null && this.Sources.Count > 0); }
public bool IsVulnerable(SemanticModel model, InvocationExpressionSyntax syntax, DiagnosticId ruleId) { //These persist from previous invocations (clear before staring) //TODO: Make this lock during execution until we call ToImmutableArray() after this is done this.Sources.Clear(); //Cheap check for class & method name if (!syntax.Expression.ToString().Contains("Process.Start")) { return(false); } //Verify full namesapce var symbol = model.GetSymbolInfo(syntax).Symbol as IMethodSymbol; if (!symbol.IsMethod("System.Diagnostics.Process", "Start")) { return(false); } //Bail if no arguments to analyze (this is covered by the ProcessStartInfo analyzer) if (syntax.ArgumentList?.Arguments.Count == 0) { return(false); } //Lots of weird cases here //: 1 argument (no) //: 2 arguments (string filename, string arguments) //: 4 arguments (string filename, no, no, no) //: 5 argumnets (string filename, string arguments, no, no, no) if (syntax.ArgumentList?.Arguments.Count == 1 || syntax.ArgumentList?.Arguments.Count == 4) { var fileNameSyntax = syntax.ArgumentList?.Arguments[0].Expression; //Custom cheap check, weed out the process start info type var fileNameSymbol = model.GetSymbolInfo(fileNameSyntax).Symbol as ILocalSymbol; if (string.Compare(fileNameSymbol?.Type.ToString(), "System.Diagnostics.ProcessStartInfo") == 0) { return(false); } var expressionAnalyzer = SyntaxNodeAnalyzerFactory.Create(fileNameSyntax); if (!expressionAnalyzer.CanIgnore(model, fileNameSyntax) && !expressionAnalyzer.CanSuppress(model, fileNameSyntax, ruleId)) { this.Sources.Add(fileNameSyntax); } } else if (syntax.ArgumentList?.Arguments.Count == 2 || syntax.ArgumentList?.Arguments.Count == 5) { var fileNameSyntax = syntax.ArgumentList?.Arguments[0].Expression; var expressionAnalyzer = SyntaxNodeAnalyzerFactory.Create(fileNameSyntax); if (!expressionAnalyzer.CanIgnore(model, fileNameSyntax) && !expressionAnalyzer.CanSuppress(model, fileNameSyntax, ruleId)) { this.Sources.Add(fileNameSyntax); } var argumenetSyntax = syntax.ArgumentList.Arguments[1].Expression; expressionAnalyzer = SyntaxNodeAnalyzerFactory.Create(argumenetSyntax); if (!expressionAnalyzer.CanIgnore(model, argumenetSyntax) && !expressionAnalyzer.CanSuppress(model, argumenetSyntax, ruleId)) { this.Sources.Add(argumenetSyntax); } } return(Sources != null && Sources.Count > 0); }