public void VisitAssignmentExpression(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { SyntaxNode right = nodeHelper.GetAssignmentRightNode(ctx.Node); SyntaxNode left = nodeHelper.GetAssignmentLeftNode(ctx.Node); var symbol = ctx.SemanticModel.GetSymbolInfo(left).Symbol; var content = right.GetText().ToString(); // Only if it is the RequiredLength property of a PasswordValidator if (!AnalyzerUtil.SymbolMatch(symbol, type: "PasswordValidator", name: "RequiredLength") || content == string.Empty) { return; } // Validates that the value is an int and that it is over the minimum value required if (!int.TryParse(right.GetText().ToString(), out var numericValue) || numericValue >= Constants.PasswordValidatorRequiredLength) { return; } var diagnostic = Diagnostic.Create(RulePasswordLength, ctx.Node.GetLocation()); ctx.ReportDiagnostic(diagnostic); }
private DiagnosticDescriptor CheckParameter(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { Optional <object> argValue = ctx.SemanticModel.GetConstantValue(nodeHelper.GetCallArgumentExpressionNodes(ctx.Node).First()); if (!argValue.HasValue) { if (Config.AuditMode) { return(WeakHashingAnalyzer.UnknownHashRule); } return(null); } if (!(argValue.Value is string value)) { return(null); } switch (value) { case WeakHashingAnalyzer.Sha1TypeName: case "SHA": case "SHA1": case "System.Security.Cryptography.HashAlgorithm": return(WeakHashingAnalyzer.Sha1Rule); case WeakHashingAnalyzer.Md5TypeName: case "MD5": return(WeakHashingAnalyzer.Md5Rule); } return(null); }
protected static void VisitSyntaxNode(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { SyntaxNode expression = nodeHelper.GetInvocationExpressionNode(ctx.Node); if (expression == null) { return; } var symbol = ctx.SemanticModel.GetSymbolInfo(ctx.Node).Symbol; if (symbol == null) { return; } //System.Random.Next() if (symbol.IsType("System.Random.Next") || symbol.IsType("System.Random.NextBytes") || symbol.IsType("System.Random.NextDouble")) { var diagnostic = Diagnostic.Create(Rule, expression.GetLocation()); ctx.ReportDiagnostic(diagnostic); } }
private void CheckAllowHtml(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { var attributes = nodeHelper.GetDeclarationAttributeNodes(ctx.Node); foreach (var attribute in attributes) { if (!nodeHelper.GetNameNode(attribute).ToString().Contains("AllowHtml")) { continue; } var attributeSymbols = ctx.SemanticModel.GetSymbolInfo(attribute).Symbol; if (attributeSymbols == null) { continue; } var containingSymbol = attributeSymbols.ContainingSymbol.ToString(); if (containingSymbol == "System.Web.Mvc.AllowHtmlAttribute") { ctx.ReportDiagnostic(Diagnostic.Create(Rule, attribute.GetLocation())); break; } } }
protected override ISymbol GetExceptionTypeSymbolFromCatchClause(CatchClauseSyntax catchNode, SemanticModel model) { Debug.Assert(catchNode != null); var typeDeclNode = catchNode.Declaration; return(typeDeclNode == null ? TypesOfInterest.SystemObject : SyntaxNodeHelper.GetSymbol(typeDeclNode.Type, model)); }
protected void VisitObjectCreation(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { var objectCreation = nodeHelper.GetNameNode(ctx.Node); if (!objectCreation.ToString().Contains("JavaScriptSerializer")) { return; } var creationSymbols = ctx.SemanticModel.GetSymbolInfo(ctx.Node).Symbol; if (creationSymbols == null || creationSymbols.ContainingSymbol.ToString() != "System.Web.Script.Serialization.JavaScriptSerializer") { return; } var arguments = nodeHelper.GetObjectCreationArgumentExpressionNodes(ctx.Node); //if there is argument it means JavaScriptSerializer(JavaScriptTypeResolver) constructor is used var firstArgument = arguments.FirstOrDefault(); if (firstArgument == null) { return; } if (ctx.SemanticModel.GetSymbolInfo(firstArgument).Symbol != null) { ctx.ReportDiagnostic(Diagnostic.Create(Rule, ctx.Node.GetLocation())); } }
protected void VisitAttributeArgument(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { var name = nodeHelper.GetNameNode(ctx.Node); if (name == null) { return; } if (!name.ToString().EndsWith("TypeNameHandling")) { return; } var symbols = ctx.SemanticModel.GetSymbolInfo(name).Symbol; if (symbols == null) { return; } if (symbols.ContainingSymbol.ToString() != "Newtonsoft.Json.JsonPropertyAttribute") { return; } ReportIfTypeNameHandlingIsNotNone(ctx, nodeHelper.GetAttributeArgumentExpresionNode(ctx.Node)); }
public void VisitInvocationSyntaxNode(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { var symbol = ctx.SemanticModel.GetSymbolInfo(ctx.Node).Symbol; switch (symbol) { case null: return; case IMethodSymbol method: bool ret = CheckType(WeakHashingAnalyzer.Sha1TypeName, WeakHashingAnalyzer.Sha1Rule, method.ReturnType, ctx); ret |= CheckType(WeakHashingAnalyzer.Md5TypeName, WeakHashingAnalyzer.Md5Rule, method.ReturnType, ctx); if (ret) { return; } break; } var symbolString = symbol.GetTypeName(); switch (symbolString) { case "System.Security.Cryptography.CryptoConfig.CreateFromName": { var methodSymbol = (IMethodSymbol)symbol; if (methodSymbol.Parameters.Length != 1) { break; } DiagnosticDescriptor rule; if ((rule = CheckParameter(ctx, nodeHelper)) != null) { SyntaxNode expression = nodeHelper.GetInvocationExpressionNode(ctx.Node); var diagnostic = Diagnostic.Create(rule, expression.GetLocation()); Report(diagnostic, ctx); } break; } case "System.Security.Cryptography.HashAlgorithm.Create": { var methodSymbol = (IMethodSymbol)symbol; DiagnosticDescriptor rule = WeakHashingAnalyzer.Sha1Rule; // default if no parameters if (methodSymbol.Parameters.Length == 0 || (methodSymbol.Parameters.Length == 1 && (rule = CheckParameter(ctx, nodeHelper)) != null)) { SyntaxNode expression = nodeHelper.GetInvocationExpressionNode(ctx.Node); var diagnostic = Diagnostic.Create(rule, expression.GetLocation()); Report(diagnostic, ctx); } break; } } }
public VbCodeEvaluation(SyntaxNodeHelper syntaxHelper, Configuration projectConfiguration, IEnumerable <TaintAnalyzerExtensionVisualBasic> extensions) { SyntaxNodeHelper = syntaxHelper; ProjectConfiguration = projectConfiguration; Extensions = extensions ?? Enumerable.Empty <TaintAnalyzerExtensionVisualBasic>(); }
private void AnalyzeNodeForXmlDocumentDerivedTypeConstructorDecl(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; IMethodSymbol methodSymbol = SyntaxNodeHelper.GetDeclaredSymbol(node, model) as IMethodSymbol; if (methodSymbol == null || methodSymbol.MethodKind != MethodKind.Constructor || !((methodSymbol.ContainingType != _xmlTypes.XmlDocument) && methodSymbol.ContainingType.DerivesFrom(_xmlTypes.XmlDocument, baseTypesOnly: true))) { return; } bool hasSetSecureXmlResolver = false; IEnumerable <SyntaxNode> assignments = _syntaxNodeHelper.GetDescendantAssignmentExpressionNodes(node); foreach (SyntaxNode a in assignments) { bool isTargetProperty; // this is intended to be an assignment, not a bug if (hasSetSecureXmlResolver = IsAssigningIntendedValueToPropertyDerivedFromType(a, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlDocumentXmlResolverProperty(s, _xmlTypes)); }, (n) => { return(SyntaxNodeHelper.NodeHasConstantValueNull(n, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(n).Type, _xmlTypes)); }, out isTargetProperty)) { break; } } if (!hasSetSecureXmlResolver) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessingInApiDesign; context.ReportDiagnostic( CreateDiagnostic( methodSymbol.Locations, rule, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlDocumentDerivedClassConstructorNoSecureXmlResolverMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ) ) ); } }
protected void VisitSyntaxNode(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { var leftNode = nodeHelper.GetAssignmentLeftNode(ctx.Node); var symbol = ctx.SemanticModel.GetSymbolInfo(leftNode).Symbol; if (symbol == null) { return; } var configuration = ConfigurationManager .Instance.GetProjectConfiguration(ctx.Options.AdditionalFiles); if (configuration.AuditMode && symbol.IsType("System.Net.ServicePointManager.CertificatePolicy")) { ctx.ReportDiagnostic(Diagnostic.Create(Rule, ctx.Node.GetLocation())); return; } if (!IsMatch(symbol)) { return; } var rightNode = GetBody(nodeHelper.GetAssignmentRightNode(ctx.Node), ctx); if (rightNode == null) { return; } var rightValue = ctx.SemanticModel.GetConstantValue(rightNode); if (!rightValue.HasValue && configuration.AuditMode) { ctx.ReportDiagnostic(Diagnostic.Create(Rule, ctx.Node.GetLocation())); return; } if (rightValue.Value is bool value && value) { ctx.ReportDiagnostic(Diagnostic.Create(Rule, ctx.Node.GetLocation())); return; } if (configuration.AuditMode) { ctx.ReportDiagnostic(Diagnostic.Create(Rule, ctx.Node.GetLocation())); } }
// Trying to find every "this.XmlResolver = [Insecure Resolve];" in methods of types derived from XmlDocment and generate a warning for each private void AnalyzeNodeForXmlDocumentDerivedTypeMethodDecl(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; IMethodSymbol methodSymbol = SyntaxNodeHelper.GetDeclaredSymbol(node, model) as IMethodSymbol; if (methodSymbol == null || // skip constructors since we report on the absence of secure assignment in AnalyzeNodeForXmlDocumentDerivedTypeConstructorDecl methodSymbol.MethodKind == MethodKind.Constructor || !((methodSymbol.ContainingType != _xmlTypes.XmlDocument) && methodSymbol.ContainingType.DerivesFrom(_xmlTypes.XmlDocument, baseTypesOnly: true))) { return; } var assignments = this._syntaxNodeHelper.GetDescendantAssignmentExpressionNodes(node); foreach (var assignment in assignments) { bool isTargetProperty; // this is intended to be an assignment, not a bug if (IsAssigningIntendedValueToPropertyDerivedFromType(assignment, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlDocumentXmlResolverProperty(s, this._xmlTypes)); }, (n) => { return(!(SyntaxNodeHelper.NodeHasConstantValueNull(n, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(n).Type, this._xmlTypes))); }, out isTargetProperty) ) { var rule = RuleDoNotUseInsecureDtdProcessingInApiDesign; context.ReportDiagnostic( CreateDiagnostic( assignment.GetLocation(), rule, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlDocumentDerivedClassSetInsecureXmlResolverInMethodMessage), methodSymbol.Name ) ) ); } } }
private void CheckValidateInput(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { foreach (var attribute in nodeHelper.GetDeclarationAttributeNodes(ctx.Node)) { if (!nodeHelper.GetNameNode(attribute).ToString().Contains("ValidateInput")) { continue; } var hasArgumentFalse = false; SyntaxNode expression = null; foreach (var arg in nodeHelper.GetAttributeArgumentNodes(attribute)) { expression = nodeHelper.GetAttributeArgumentExpresionNode(arg); var expressionValue = ctx.SemanticModel.GetConstantValue(expression); if (!expressionValue.HasValue) { continue; } if (expressionValue.Value is bool value && value == false) { hasArgumentFalse = true; break; } } if (!hasArgumentFalse) { continue; } var attributeSymbols = ctx.SemanticModel.GetSymbolInfo(attribute).Symbol; if (attributeSymbols == null) { continue; } var containingSymbol = attributeSymbols.ContainingSymbol.ToString(); if (containingSymbol != "System.Web.Mvc.ValidateInputAttribute") { continue; } ctx.ReportDiagnostic(Diagnostic.Create(Rule, expression.GetLocation())); return; } }
private void AnalyzeNodeForDtdProcessingProperties(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel semanticModel = context.SemanticModel; SyntaxNode lhs = _syntaxNodeHelper.GetAssignmentLeftNode(node); if (lhs == null) { return; } IPropertySymbol property = SyntaxNodeHelper.GetCalleePropertySymbol(lhs, semanticModel); if (property == null) { return; } if (property.MatchPropertyDerivedByName(_xmlTypes.XmlDocument, SecurityMemberNames.InnerXml)) //FxCop CA3058 { DiagnosticDescriptor rule = RuleDoNotUseInsecureDTDProcessing; context.ReportDiagnostic( Diagnostic.Create( rule, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.DoNotUseSetInnerXmlMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, semanticModel) ) ) ); } else if (property.MatchPropertyDerivedByName(_xmlTypes.DataViewManager, SecurityMemberNames.DataViewSettingCollectionString)) //FxCop CA3065 { DiagnosticDescriptor rule = RuleDoNotUseInsecureDTDProcessing; context.ReportDiagnostic( Diagnostic.Create( rule, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.ReviewDtdProcessingPropertiesMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, semanticModel) ) ) ); } }
protected static void VisitSyntaxNode(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { var leftNode = nodeHelper.GetAssignmentLeftNode(ctx.Node); if (!nodeHelper.IsSimpleMemberAccessExpressionNode(leftNode)) { return; } var symbolMemberAccess = ctx.SemanticModel.GetSymbolInfo(leftNode).Symbol; if (IsMatch(symbolMemberAccess)) { var diagnostic = Diagnostic.Create(Rule, ctx.Node.GetLocation()); ctx.ReportDiagnostic(diagnostic); } }
protected void VisitAssignment(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { var leftNode = nodeHelper.GetAssignmentLeftNode(ctx.Node); if (!leftNode.ToString().EndsWith("TypeNameHandling")) { return; } var symbols = ctx.SemanticModel.GetSymbolInfo(leftNode).Symbol; if (symbols.ContainingSymbol.ToString() != "Newtonsoft.Json.JsonSerializerSettings") { return; } ReportIfTypeNameHandlingIsNotNone(ctx, nodeHelper.GetAssignmentRightNode(ctx.Node)); }
public Violation(Diagnostic diagnostic) { Rule = diagnostic.Id; Message = diagnostic.GetMessage(); LineNumber = diagnostic.Location.GetLineSpan().Span.Start.Line + 1; Source = diagnostic.Location.GetLineSpan().Path; RuleNamespace = diagnostic.Descriptor.Category; var classDeclarationSyntax = diagnostic.Location.SourceTree.GetRoot().DescendantNodes().OfType <ClassDeclarationSyntax>().FirstOrDefault(); NamespaceDeclarationSyntax namespaceDeclarationSyntax = null; if (!SyntaxNodeHelper.TryGetParentSyntax(classDeclarationSyntax, out namespaceDeclarationSyntax)) { return; } var namespaceName = namespaceDeclarationSyntax.Name.ToString(); var fullClassName = namespaceName + "." + classDeclarationSyntax.Identifier.ToString(); Section = fullClassName; }
protected static void VisitSyntaxNode(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { var expression = nodeHelper.GetInvocationExpressionNode(ctx.Node); if (expression != null) { var symbol = ctx.SemanticModel.GetSymbolInfo(ctx.Node).Symbol; if (symbol != null) { foreach (string cipher in BadCipherCreate) { if (!symbol.IsType(cipher)) { continue; } var diagnostic = Diagnostic.Create(Rule, expression.GetLocation(), cipher); ctx.ReportDiagnostic(diagnostic); } } } if (nodeHelper.IsObjectCreationExpressionNode(ctx.Node)) { var symbol = ctx.SemanticModel.GetSymbolInfo(ctx.Node).Symbol; if (symbol != null) { foreach (string cipher in BadCipherProvider) { if (!symbol.ContainingSymbol.IsType(cipher)) { continue; } var diagnostic = Diagnostic.Create(Rule, ctx.Node.GetLocation(), cipher); ctx.ReportDiagnostic(diagnostic); } } } }
protected static void VisitSyntaxNode(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { var leftNode = nodeHelper.GetAssignmentLeftNode(ctx.Node); if (!nodeHelper.IsSimpleMemberAccessExpressionNode(leftNode)) { return; } var symbolMemberAccess = ctx.SemanticModel.GetSymbolInfo(leftNode).Symbol; if (AnalyzerUtil.SymbolMatch(symbolMemberAccess, type: "ServicePointManager", name: "ServerCertificateValidationCallback") || AnalyzerUtil.SymbolMatch(symbolMemberAccess, type: "ServicePointManager", name: "CertificatePolicy")) { var diagnostic = Diagnostic.Create(Rule, ctx.Node.GetLocation()); ctx.ReportDiagnostic(diagnostic); } }
protected void VisitAssignment(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { // todo: if PasswordField is reintroduced to Behaviors need to filter warnings covered by taint analyzer var leftNode = nodeHelper.GetAssignmentLeftNodeName(ctx.Node); if (!IsPasswordField(leftNode, ctx.Options.AdditionalFiles)) { return; } var rightNode = nodeHelper.GetAssignmentRightNode(ctx.Node); if (rightNode == null) { return; } var constValue = ctx.SemanticModel.GetConstantValue(rightNode); if (!constValue.HasValue) { return; } if (!(constValue.Value is string value)) { return; } if (value.Equals(string.Empty)) { return; } var diagnostic = Diagnostic.Create(Rule, ctx.Node.GetLocation()); ctx.ReportDiagnostic(diagnostic); }
private void CheckUnvalidated(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { var name = nodeHelper.GetNameNode(ctx.Node); if (name.ToString() != "Unvalidated") { return; } var memberAccessSymbol = ctx.SemanticModel.GetSymbolInfo(ctx.Node).Symbol; if (memberAccessSymbol == null) { return; } var containingSymbol = memberAccessSymbol.ContainingSymbol.ToString(); if (containingSymbol == "System.Web.Helpers.Validation" || containingSymbol == "System.Web.HttpRequestBase") { ctx.ReportDiagnostic(Diagnostic.Create(Rule, name.GetLocation())); } }
protected static void VisitSyntaxNode(SyntaxNodeAnalysisContext ctx, SyntaxNodeHelper nodeHelper) { var expression = nodeHelper.GetInvocationExpressionNode(ctx.Node); if (expression != null) { var symbol = ctx.SemanticModel.GetSymbolInfo(ctx.Node).Symbol; foreach (string cipher in BadCiphers) { if (!AnalyzerUtil.SymbolMatch(symbol, type: cipher, name: "Create")) { continue; } var diagnostic = Diagnostic.Create(Rule, expression.GetLocation(), cipher); ctx.ReportDiagnostic(diagnostic); } } if (nodeHelper.IsObjectCreationExpressionNode(ctx.Node)) { var symbol = ctx.SemanticModel.GetSymbolInfo(ctx.Node).Symbol; foreach (string cipher in BadCiphers) { if (!AnalyzerUtil.SymbolMatch(symbol, type: cipher + "CryptoServiceProvider")) { continue; } var diagnostic = Diagnostic.Create(Rule, ctx.Node.GetLocation(), cipher); ctx.ReportDiagnostic(diagnostic); } } }
private void AnalyzeNodeForXsltSettings(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; SyntaxNode lhs = _syntaxNodeHelper.GetAssignmentLeftNode(node); SyntaxNode rhs = _syntaxNodeHelper.GetAssignmentRightNode(node); if (lhs == null || rhs == null) { return; } ISymbol lhsSymbol = SyntaxNodeHelper.GetSymbol(lhs, model); if (lhsSymbol == null) { return; } IMethodSymbol rhsMethodSymbol = _syntaxNodeHelper.GetCalleeMethodSymbol(rhs, model); IPropertySymbol rhsPropertySymbol = SyntaxNodeHelper.GetCalleePropertySymbol(rhs, model); if (SecurityDiagnosticHelpers.IsXsltSettingsCtor(rhsMethodSymbol, _xmlTypes)) { XsltSettingsEnvironment env = new XsltSettingsEnvironment(); _xsltSettingsEnvironments[lhsSymbol] = env; env.XsltSettingsSymbol = lhsSymbol; env.XsltSettingsDefinitionSymbol = rhsMethodSymbol; env.XsltSettingsDefinition = node; env.EnclosingConstructSymbol = _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model); //default both properties are disbled env.IsDocumentFunctionDisabled = true; env.IsScriptDisabled = true; // XsltSettings Constructor (Boolean, Boolean) if (rhsMethodSymbol.Parameters.Any()) { IEnumerable <SyntaxNode> argumentExpressionNodes = _syntaxNodeHelper.GetObjectCreationArgumentExpressionNodes(rhs); env.IsDocumentFunctionDisabled = SyntaxNodeHelper.NodeHasConstantValueBoolFalse(argumentExpressionNodes.ElementAt(0), model); env.IsScriptDisabled = SyntaxNodeHelper.NodeHasConstantValueBoolFalse(argumentExpressionNodes.ElementAt(1), model); } foreach (SyntaxNode arg in _syntaxNodeHelper.GetObjectInitializerExpressionNodes(rhs)) { SyntaxNode argLhs = _syntaxNodeHelper.GetAssignmentLeftNode(arg); SyntaxNode argRhs = _syntaxNodeHelper.GetAssignmentRightNode(arg); ISymbol argLhsSymbol = SyntaxNodeHelper.GetSymbol(argLhs, model); // anything other than a constant false is treated as true if (SecurityDiagnosticHelpers.IsXsltSettingsEnableDocumentFunctionProperty(argLhsSymbol as IPropertySymbol, _xmlTypes)) { env.IsDocumentFunctionDisabled = SyntaxNodeHelper.NodeHasConstantValueBoolFalse(argRhs, model); } else if (SecurityDiagnosticHelpers.IsXsltSettingsEnableScriptProperty(argLhsSymbol as IPropertySymbol, _xmlTypes)) { env.IsScriptDisabled = SyntaxNodeHelper.NodeHasConstantValueBoolFalse(argRhs, model); } } } else if (SecurityDiagnosticHelpers.IsXsltSettingsDefaultProperty(rhsPropertySymbol, _xmlTypes)) { XsltSettingsEnvironment env = new XsltSettingsEnvironment(); _xsltSettingsEnvironments[lhsSymbol] = env; env.XsltSettingsSymbol = lhsSymbol; env.XsltSettingsDefinitionSymbol = rhsPropertySymbol; env.XsltSettingsDefinition = node; env.EnclosingConstructSymbol = _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model); env.IsDocumentFunctionDisabled = true; env.IsScriptDisabled = true; } else if (SecurityDiagnosticHelpers.IsXsltSettingsTrustedXsltProperty(rhsPropertySymbol, _xmlTypes)) { XsltSettingsEnvironment env = new XsltSettingsEnvironment(); _xsltSettingsEnvironments[lhsSymbol] = env; env.XsltSettingsSymbol = lhsSymbol; env.XsltSettingsDefinitionSymbol = rhsPropertySymbol; env.XsltSettingsDefinition = node; env.EnclosingConstructSymbol = _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model); } else { bool isXlstSettingsEnableDocumentFunctionProperty = SecurityDiagnosticHelpers.IsXsltSettingsEnableDocumentFunctionProperty(lhsSymbol as IPropertySymbol, _xmlTypes); bool isXlstSettingsEnableScriptProperty = SecurityDiagnosticHelpers.IsXsltSettingsEnableScriptProperty(lhsSymbol as IPropertySymbol, _xmlTypes); if (isXlstSettingsEnableDocumentFunctionProperty || isXlstSettingsEnableScriptProperty) { SyntaxNode lhsExpressionNode = _syntaxNodeHelper.GetMemberAccessExpressionNode(lhs); if (lhsExpressionNode == null) { return; } ISymbol lhsExpressionSymbol = SyntaxNodeHelper.GetSymbol(lhsExpressionNode, model); if (lhsExpressionSymbol == null) { return; } if (!_xsltSettingsEnvironments.TryGetValue(lhsExpressionSymbol, out XsltSettingsEnvironment env)) { env = new XsltSettingsEnvironment { XsltSettingsSymbol = lhsExpressionSymbol }; _xsltSettingsEnvironments[lhsExpressionSymbol] = env; } if (isXlstSettingsEnableDocumentFunctionProperty) { env.IsDocumentFunctionDisabled = SyntaxNodeHelper.NodeHasConstantValueBoolFalse(rhs, model); } else if (isXlstSettingsEnableScriptProperty) { env.IsScriptDisabled = SyntaxNodeHelper.NodeHasConstantValueBoolFalse(rhs, model); } } } }
public SymbolAndNodeAnalyzer(CompilationSecurityTypes xmlTypes, SyntaxNodeHelper helper, Version targetFrameworkVersion) { _xmlTypes = xmlTypes; _syntaxNodeHelper = helper; _isFrameworkSecure = targetFrameworkVersion != null && targetFrameworkVersion >= SymbolAndNodeAnalyzer.s_minSecureFxVersion; }
private bool IsAssigningIntendedValueToPropertyDerivedFromType(SyntaxNode assignment, SemanticModel model, Func <IPropertySymbol, bool> isTargetPropertyFunc, Func <SyntaxNode, bool> isIntendedValueFunc, out bool isTargetProperty) { bool isIntendedValue; SyntaxNode left = _syntaxNodeHelper.GetAssignmentLeftNode(assignment); SyntaxNode right = _syntaxNodeHelper.GetAssignmentRightNode(assignment); IPropertySymbol leftSymbol = SyntaxNodeHelper.GetCalleePropertySymbol(left, model); isTargetProperty = isTargetPropertyFunc(leftSymbol); if (!isTargetProperty) { return(false); } // call to isIntendedValueFunc must be after checking isTargetProperty // since the logic of isIntendedValueFunc relies on corresponding SyntaxNode isIntendedValue = isIntendedValueFunc(right); // Here's an example that needs some extra check: // // class TestClass : XmlDocument // { // private XmlDocument doc = new XmlDocument(); // public TestClass(XmlDocument doc) // { // this.doc.XmlResolver = null; // } // } // // Even though the assignment would return true for both isTargetPropertyFunc and isIntendedValueFunc, // it is not setting the actual property for this class. // The goal is to find all assignment like in the example above, "this.xxx.xxx.Property = ...;". // For simplicity, here we adopt a simple but inaccurate logic: // If the target is a member access node, then the only pattern we are looking for is "this.Property" SyntaxNode memberAccessNode = _syntaxNodeHelper.GetDescendantMemberAccessExpressionNodes(left).FirstOrDefault(); // if assignment target doesn't have any member access node, // then we treat it as an instance property access without explicit 'this' ('Me' in VB) if (memberAccessNode == null) { //stop here, to avoid false positive, as long as there's one setting <Property> to secure value, we are happy return(isIntendedValue); } SyntaxNode exp = _syntaxNodeHelper.GetMemberAccessExpressionNode(memberAccessNode); ISymbol expSymbol = SyntaxNodeHelper.GetSymbol(exp, model); isTargetProperty = expSymbol.Kind == SymbolKind.Parameter && ((IParameterSymbol)expSymbol).IsThis; if (!isTargetProperty) { return(false); } SyntaxNode name = _syntaxNodeHelper.GetMemberAccessNameNode(memberAccessNode); ISymbol nameSymbol = SyntaxNodeHelper.GetSymbol(name, model); isTargetProperty = isTargetPropertyFunc(nameSymbol as IPropertySymbol); if (!isTargetProperty) { return(false); } // stop here, same reason as stated above return(isIntendedValue); }
private void AnalyzeNodeForXmlTextReaderDerivedTypeMethodDecl(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; if (!(SyntaxNodeHelper.GetDeclaredSymbol(node, model) is IMethodSymbol methodSymbol) || !((!Equals(methodSymbol.ContainingType, _xmlTypes.XmlTextReader)) && methodSymbol.ContainingType.DerivesFrom(_xmlTypes.XmlTextReader, baseTypesOnly: true))) { return; } // If the default value are not secure, the AnalyzeNodeForXmlTextReaderDerivedTypeConstructorDecl would be skipped, // therefoer we need to check constructor for any insecure settings. // Otherwise, we skip checking constructors if (_isFrameworkSecure && methodSymbol.MethodKind == MethodKind.Constructor) { return; } bool hasSetXmlResolver = false; bool hasSetInsecureXmlResolver = true; bool isDtdProcessingSet = false; bool isDtdProcessingEnabled = true; List <Location> locs = null; IEnumerable <SyntaxNode> assignments = _syntaxNodeHelper.GetDescendantAssignmentExpressionNodes(node); foreach (SyntaxNode assignment in assignments) { bool ret; ret = IsAssigningIntendedValueToPropertyDerivedFromType(assignment, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverProperty(s, _xmlTypes)); }, (n) => { return(!(SyntaxNodeHelper.NodeHasConstantValueNull(n, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(n).Type, _xmlTypes))); }, out bool isTargetProperty ); if (isTargetProperty) { hasSetXmlResolver = true; hasSetInsecureXmlResolver &= ret; // use 'AND' to avoid false positives (but imcrease false negative rate) if (ret) { if (locs == null) { locs = new List <Location>(); } locs.Add(assignment.GetLocation()); } continue; } ret = IsAssigningIntendedValueToPropertyDerivedFromType(assignment, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingProperty(s, _xmlTypes)); }, (n) => { return(SyntaxNodeHelper.GetSymbol(n, model).MatchFieldByName(_xmlTypes.DtdProcessing, SecurityMemberNames.Parse)); }, out isTargetProperty); if (isTargetProperty) { isDtdProcessingSet = true; isDtdProcessingEnabled &= ret; // use 'AND' to avoid false positives (but imcrease false negative rate) if (ret) { if (locs == null) { locs = new List <Location>(); } locs.Add(assignment.GetLocation()); } } } // neither XmlResolver nor DtdProcessing is explicitly set if (!(hasSetXmlResolver || isDtdProcessingSet)) { return; } // explicitly set XmlResolver and/or DtdProcessing to secure value else if (!hasSetInsecureXmlResolver || !isDtdProcessingEnabled) { return; } // didn't explicitly set either one of XmlResolver and DtdProcessing to secure value // but explicitly set XmlResolver and/or DtdProcessing to insecure value else { DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessingInApiDesign; // TODO: Only first location is shown in error, maybe we want to report on method instead? // Or on each insecure assignment? context.ReportDiagnostic( CreateDiagnostic( locs, rule, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlTextReaderDerivedClassSetInsecureSettingsInMethodMessage), methodSymbol.Name ) ) ); } }
private void AnalyzeNodeForXmlTextReaderDerivedTypeConstructorDecl(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; if (!(SyntaxNodeHelper.GetDeclaredSymbol(node, model) is IMethodSymbol methodSymbol) || methodSymbol.MethodKind != MethodKind.Constructor || !((!Equals(methodSymbol.ContainingType, _xmlTypes.XmlTextReader)) && methodSymbol.ContainingType.DerivesFrom(_xmlTypes.XmlTextReader, baseTypesOnly: true))) { return; } bool hasSetSecureXmlResolver = false; bool isDtdProcessingDisabled = false; IEnumerable <SyntaxNode> assignments = _syntaxNodeHelper.GetDescendantAssignmentExpressionNodes(node); foreach (SyntaxNode assignment in assignments) { bool isTargetProperty = false; hasSetSecureXmlResolver = hasSetSecureXmlResolver || IsAssigningIntendedValueToPropertyDerivedFromType(assignment, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverProperty(s, _xmlTypes)); }, (n) => { return(SyntaxNodeHelper.NodeHasConstantValueNull(n, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(n).Type, _xmlTypes)); }, out isTargetProperty); if (isTargetProperty) { continue; } isDtdProcessingDisabled = isDtdProcessingDisabled || IsAssigningIntendedValueToPropertyDerivedFromType(assignment, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingProperty(s, _xmlTypes)); }, (n) => { return(!SyntaxNodeHelper.GetSymbol(n, model).MatchFieldByName(_xmlTypes.DtdProcessing, SecurityMemberNames.Parse)); }, out isTargetProperty); if (hasSetSecureXmlResolver && isDtdProcessingDisabled) { return; } } DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessingInApiDesign; context.ReportDiagnostic( CreateDiagnostic( methodSymbol.Locations, rule, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlTextReaderDerivedClassConstructorNoSecureSettingsMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model, context.CancellationToken) ) ) ); }
public SyntaxNodeAnalyzer(CompilationSecurityTypes xmlTypes, SyntaxNodeHelper helper) { _xmlTypes = xmlTypes; _syntaxNodeHelper = helper; }
private void AnalyzeNodeForXslCompiledTransformLoad(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; IMethodSymbol methodSymbol = _syntaxNodeHelper.GetCalleeMethodSymbol(node, model); if (SecurityDiagnosticHelpers.IsXslCompiledTransformLoad(methodSymbol, _xmlTypes)) { bool isSecureResolver; bool isSecureSettings; bool isSetInBlock; int xmlResolverIndex = SecurityDiagnosticHelpers.GetXmlResolverParameterIndex(methodSymbol, _xmlTypes); int xsltSettingsIndex = SecurityDiagnosticHelpers.GetXsltSettingsParameterIndex(methodSymbol, _xmlTypes); // Overloads with no XmlResolver and XstlSettings specified are secure since they all have folowing behavior: // 1. An XmlUrlResolver with no user credentials is used to process any xsl:import or xsl:include elements. // 2. The document() function is disabled. // 3. Embedded scripts are not supported. if (xmlResolverIndex >= 0 && xsltSettingsIndex >= 0) { IEnumerable <SyntaxNode> argumentExpressionNodes = _syntaxNodeHelper.GetInvocationArgumentExpressionNodes(node); SyntaxNode resolverNode = argumentExpressionNodes.ElementAt(xmlResolverIndex); isSecureResolver = SyntaxNodeHelper.NodeHasConstantValueNull(resolverNode, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(resolverNode).Type, _xmlTypes); SyntaxNode settingsNode = argumentExpressionNodes.ElementAt(xsltSettingsIndex); ISymbol settingsSymbol = SyntaxNodeHelper.GetSymbol(settingsNode, model); // 1. pass null or XsltSettings.Default as XsltSetting : secure if (settingsSymbol == null || SecurityDiagnosticHelpers.IsXsltSettingsDefaultProperty(settingsSymbol as IPropertySymbol, _xmlTypes)) { isSetInBlock = true; isSecureSettings = true; } // 2. XsltSettings.TrustedXslt : insecure else if (SecurityDiagnosticHelpers.IsXsltSettingsTrustedXsltProperty(settingsSymbol as IPropertySymbol, _xmlTypes)) { isSetInBlock = true; isSecureSettings = false; } // 3. check xsltSettingsEnvironments, if IsScriptDisabled && IsDocumentFunctionDisabled then secure, else insecure else if (_xsltSettingsEnvironments.TryGetValue(settingsSymbol, out XsltSettingsEnvironment env)) { isSetInBlock = false; isSecureSettings = env.IsDocumentFunctionDisabled && env.IsScriptDisabled; } //4. symbol for settings is not found => passed in without any change => assume insecure else { isSetInBlock = true; isSecureSettings = false; } if (!isSecureSettings && !isSecureResolver) { LocalizableResourceString message = SecurityDiagnosticHelpers.GetLocalizableResourceString( isSetInBlock ? nameof(MicrosoftNetFrameworkAnalyzersResources.XslCompiledTransformLoadInsecureConstructedMessage) : nameof(MicrosoftNetFrameworkAnalyzersResources.XslCompiledTransformLoadInsecureInputMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model, context.CancellationToken) ); context.ReportDiagnostic( Diagnostic.Create( RuleDoNotUseInsecureXSLTScriptExecution, node.GetLocation(), message ) ); } } } }
protected XxeAnalyzer(XxeSecurityTypes xmlTypes, SyntaxNodeHelper helper, Version frameworkVersion) { XmlTypes = xmlTypes; SyntaxNodeHelper = helper; AreDefaultsSecure = frameworkVersion >= new Version(4, 5, 2); }