public bool IsVulnerable(SemanticModel model, MethodDeclarationSyntax syntax) { //Quick check - public methods only if (!syntax.Modifiers.Any(i => i.Kind() == SyntaxKind.PublicKeyword)) { return(false); } //Verify the return type is an expected value. if (syntax == null || !syntax.ContainsReturnType(model, _ACTION_RESULT_NAMESPACES)) { return(false); } //Assuming a good design pattern where GET requests (no method decoration) actually //only retrieve data and do not make a data modifications. We all know this isn't always the case, //but this is to reduce false positives on methods that are not vulnerable if (syntax.AttributeLists.Count == 0) { return(false); } //Search for HttpPost, HttpPut, HttpPatch, and HttpDelete decorators on the action var dataModification = false; var validateAntiForgeryToken = false; var anonymousMethod = false; foreach (var attributeSyntax in syntax.AttributeLists) { foreach (var attribute in attributeSyntax.Attributes) { //Check for action verb (post, put, delete, etc.) if (!dataModification && _MODIFICATION_VERB_ATTRIBUTES.Split('|').Contains(attribute.Name?.ToString())) { dataModification = true; } //Check for anti forgery token method if (!validateAntiForgeryToken && string.Compare(attribute.Name?.ToString(), _ANTI_FORGERY_TOKEN_ATTRIBUTE) == 0) { validateAntiForgeryToken = true; } //Check for anoynmous attribute (reduces fps) if (!anonymousMethod && string.Compare(attribute.Name?.ToString(), _ANONYMOUS_ATTRIBUTE) == 0) { anonymousMethod = true; } } } return(dataModification && !validateAntiForgeryToken && !anonymousMethod); }
public List <SyntaxNode> IsVulnerable(SemanticModel model, ClassDeclarationSyntax syntax) { List <SyntaxNode> sources = new List <SyntaxNode>(); //Check the class declaration if (!hasBaseClass(model, syntax)) { return(sources); } //Pull the list of candidate methods var methodDeclarations = syntax.Members.Where(i => i.Kind() == SyntaxKind.MethodDeclaration).ToList(); foreach (MemberDeclarationSyntax member in methodDeclarations) { MethodDeclarationSyntax methodSyntax = member as MethodDeclarationSyntax; if (methodSyntax == null) { continue; } //Quick check - public methods only if (!methodSyntax.Modifiers.Any(i => i.Kind() == SyntaxKind.PublicKeyword)) { continue; } //If does not have the correct return type if (!methodSyntax.ContainsReturnType(model, _ACTION_RESULT_SYNTAXES)) { continue; } //Check method declaration for attributes if (isMissingAuthorizeAttribute(model, methodSyntax.AttributeLists)) { sources.Add(methodSyntax.ReturnType); } } return(sources); }