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);
        }
コード例 #2
0
        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);
        }
コード例 #4
0
        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);
        }