private void AnalyzeNodeForXmlTextReaderDerivedTypeConstructorDecl(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; if (SyntaxNodeHelper.GetDeclaredSymbol(node, model) is not 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) ) ) ); }
private void AnalyzeObjectCreationForXmlDocument(OperationAnalysisContext context, ISymbol variable, IObjectCreationOperation objCreation) { XmlDocumentEnvironment xmlDocumentEnvironment; if (variable == null || !_xmlDocumentEnvironments.TryGetValue(variable, out xmlDocumentEnvironment)) { xmlDocumentEnvironment = new XmlDocumentEnvironment { IsSecureResolver = false, IsXmlResolverSet = false }; } xmlDocumentEnvironment.XmlDocumentDefinition = objCreation.Syntax; SyntaxNode node = objCreation.Syntax; bool isXmlDocumentSecureResolver = false; if (objCreation.Constructor.ContainingType != _xmlTypes.XmlDocument) { isXmlDocumentSecureResolver = true; } // propertyInitlizer is not returned any more // and no way to get propertysymbol if (objCreation.Initializer != null) { foreach (IOperation init in objCreation.Initializer.Initializers) { if (init is IAssignmentOperation assign) { var propValue = assign.Value; IPropertySymbol prop = context.Compilation.GetSemanticModel(context.Operation.Syntax.SyntaxTree)?.GetSymbolInfo(assign.Target.Syntax).Symbol as IPropertySymbol; if (prop == null) { continue; } if (prop.MatchPropertyDerivedByName(_xmlTypes.XmlDocument, "XmlResolver")) { IConversionOperation operation = propValue as IConversionOperation; if (operation == null) { return; } if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { isXmlDocumentSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { isXmlDocumentSecureResolver = true; } else // Non secure resolvers { return; } } } } } xmlDocumentEnvironment.IsSecureResolver = isXmlDocumentSecureResolver; if (variable != null) { _xmlDocumentEnvironments[variable] = xmlDocumentEnvironment; } else if (!xmlDocumentEnvironment.IsSecureResolver) // Insecure temp object { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlDocumentWithNoSecureResolverMessage) ) ); context.ReportDiagnostic(diag); } }
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 AnalyzeObjectCreationForXmlDocument(OperationAnalysisContext context, ISymbol variable, IObjectCreationOperation objCreation) { if (variable == null || !_xmlDocumentEnvironments.TryGetValue(variable, out var xmlDocumentEnvironment)) { xmlDocumentEnvironment = new XmlDocumentEnvironment { IsSecureResolver = false, IsXmlResolverSet = false }; } xmlDocumentEnvironment.XmlDocumentDefinition = objCreation.Syntax; SyntaxNode node = objCreation.Syntax; bool isXmlDocumentSecureResolver = false; if (!Equals(objCreation.Constructor.ContainingType, _xmlTypes.XmlDocument)) { isXmlDocumentSecureResolver = true; } // propertyInitlizer is not returned any more // and no way to get propertysymbol if (objCreation.Initializer != null) { foreach (IOperation init in objCreation.Initializer.Initializers) { if (init is IAssignmentOperation assign) { var propValue = assign.Value; if (!(assign.Target is IPropertyReferenceOperation propertyReference)) { continue; } var prop = propertyReference.Property; if (prop.MatchPropertyDerivedByName(_xmlTypes.XmlDocument, "XmlResolver")) { if (!(propValue is IConversionOperation operation)) { return; } if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { isXmlDocumentSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { isXmlDocumentSecureResolver = true; } else // Non secure resolvers { ReportDiagnostic(assign.Syntax, context); return; } } else { AnalyzeNeverSetProperties(context, prop, assign.Syntax.GetLocation()); } } } } xmlDocumentEnvironment.IsSecureResolver = isXmlDocumentSecureResolver; if (variable != null) { _xmlDocumentEnvironments[variable] = xmlDocumentEnvironment; } else if (!xmlDocumentEnvironment.IsSecureResolver) // Insecure temp object { ReportDiagnostic(node, context); } return;
private void AnalyzeObjectCreationForXmlDocument(OperationAnalysisContext context, ISymbol variable, IObjectCreationOperation objCreation) { // create new environment representation if does not already exist if (variable == null || !_xmlDocumentEnvironments.TryGetValue(variable, out var xmlDocumentEnvironment)) { xmlDocumentEnvironment = new XmlDocumentEnvironment(_isFrameworkSecure); } xmlDocumentEnvironment.XmlDocumentDefinition = objCreation.Syntax; SyntaxNode node = objCreation.Syntax; // initial XmlResolver secure value dependent on whether framework version secure // < .NET 4.5.2 insecure - XmlDocument would set XmlResolver as XmlUrlResolver // >= .NET 4.5.2 secure - XmlDocument would set XmlResolver as null bool isXmlDocumentSecureResolver = _isFrameworkSecure; if (!Equals(objCreation.Constructor.ContainingType, _xmlTypes.XmlDocument)) { isXmlDocumentSecureResolver = true; } // propertyInitlizer is not returned any more // and no way to get propertysymbol if (objCreation.Initializer != null) { foreach (IOperation init in objCreation.Initializer.Initializers) { if (init is IAssignmentOperation assign) { var propValue = assign.Value; if (assign.Target is not IPropertyReferenceOperation propertyReference) { continue; } var prop = propertyReference.Property; if (prop.MatchPropertyDerivedByName(_xmlTypes.XmlDocument, "XmlResolver")) { if (propValue is not IConversionOperation operation) { return; } // if XmlResolver declared as XmlSecureResolver by initializer if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { isXmlDocumentSecureResolver = true; } // if XmlResolver declared as null by initializer else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { isXmlDocumentSecureResolver = true; } // otherwise insecure resolver else { context.ReportDiagnostic(assign.Syntax.CreateDiagnostic(RuleXmlDocumentWithNoSecureResolver)); return; } } else { AnalyzeNeverSetProperties(context, prop, assign.Syntax.GetLocation()); } } } } xmlDocumentEnvironment.IsSecureResolver = isXmlDocumentSecureResolver; // if XmlDocument object not temporary, add environment to dictionary if (variable != null) { _xmlDocumentEnvironments[variable] = xmlDocumentEnvironment; } // else is temporary (variable null) and XmlResolver insecure, then report now else if (!xmlDocumentEnvironment.IsSecureResolver) { context.ReportDiagnostic(node.CreateDiagnostic(RuleXmlDocumentWithNoSecureResolver)); } return; }
private void AnalyzeObjectCreationForXmlDocument(OperationAnalysisContext context, ISymbol variable, IObjectCreationExpression objCreation) { XmlDocumentEnvironment xmlDocumentEnvironment; if (variable == null || !_xmlDocumentEnvironments.ContainsKey(variable)) { xmlDocumentEnvironment = new XmlDocumentEnvironment { IsSecureResolver = false, IsXmlResolverSet = false }; } else { xmlDocumentEnvironment = _xmlDocumentEnvironments[variable]; } xmlDocumentEnvironment.XmlDocumentDefinition = objCreation.Syntax; SyntaxNode node = objCreation.Syntax; bool isXmlDocumentSecureResolver = false; if (objCreation.Constructor.ContainingType != _xmlTypes.XmlDocument) { isXmlDocumentSecureResolver = true; } foreach (ISymbolInitializer init in objCreation.MemberInitializers) { if (init is IPropertyInitializer prop) { if (prop.InitializedProperty.MatchPropertyDerivedByName(_xmlTypes.XmlDocument, "XmlResolver")) { IConversionExpression operation = prop.Value as IConversionExpression; if (operation == null) { return; } if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { isXmlDocumentSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { isXmlDocumentSecureResolver = true; } else // Non secure resolvers { if (operation.Operand is IObjectCreationExpression xmlResolverObjCreated) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, prop.Syntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlDocumentWithNoSecureResolverMessage) ) ); context.ReportDiagnostic(diag); } return; } } else { AnalyzeNeverSetProperties(context, prop.InitializedProperty, prop.Syntax.GetLocation()); } } } xmlDocumentEnvironment.IsSecureResolver = isXmlDocumentSecureResolver; if (variable != null) { _xmlDocumentEnvironments[variable] = xmlDocumentEnvironment; } else if (!xmlDocumentEnvironment.IsSecureResolver) // Insecure temp object { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlDocumentWithNoSecureResolverMessage) ) ); context.ReportDiagnostic(diag); } }
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 ) ); } } } }
private void AnalyzePropertyAssignment(IPropertySymbol symbol, SyntaxNode lhs, SyntaxNode rhs, SemanticModel model) { if (SecurityDiagnosticHelpers.IsXmlDocumentXmlResolverPropertyDerived(symbol, XmlTypes)) { ISymbol lhsExpressionSymbol = SyntaxNodeHelper.GetSymbol(lhs, model); if (lhsExpressionSymbol == null) { return; } var env = GetEnvironment(lhsExpressionSymbol, lhs, XmlDocumentEnvironments, TempXmlDocumentEnvironments); bool oldIsSecureResolver = env.IsSecureResolver; env.IsSecureResolver = SyntaxNodeHelper.NodeHasConstantValueNull(rhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(rhs).Type, XmlTypes); if (oldIsSecureResolver && !env.IsSecureResolver) { env.Definition = rhs; } } else if (SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverPropertyDerived(symbol, XmlTypes)) { ISymbol lhsExpressionSymbol = SyntaxNodeHelper.GetSymbol(lhs, model); if (lhsExpressionSymbol == null) { return; } var env = GetEnvironment(lhsExpressionSymbol, lhs, XmlTextReaderEnvironments, TempXmlTextReaderEnvironments); bool oldIsSecureResolver = env.IsSecureResolver; env.IsSecureResolver = SyntaxNodeHelper.NodeHasConstantValueNull(rhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(rhs).Type, XmlTypes); if (oldIsSecureResolver && !env.IsSecureResolver) { env.Definition = rhs; } } else if (SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingPropertyDerived(symbol, XmlTypes)) { ISymbol lhsExpressionSymbol = SyntaxNodeHelper.GetSymbol(lhs, model); if (lhsExpressionSymbol == null) { return; } var env = GetEnvironment(lhsExpressionSymbol, lhs, XmlTextReaderEnvironments, TempXmlTextReaderEnvironments); bool oldIsDtdProcessingDisabled = env.IsDtdProcessingDisabled; env.IsDtdProcessingDisabled = !SyntaxNodeHelper.NodeHasConstantValue(rhs, model, 2 /*DtdProcessing.Parse*/); if (oldIsDtdProcessingDisabled && !env.IsDtdProcessingDisabled) { env.Definition = rhs; } } else if (SecurityDiagnosticHelpers.IsXmlTextReaderProhibitDtdPropertyDerived(symbol, XmlTypes)) { ISymbol lhsExpressionSymbol = SyntaxNodeHelper.GetSymbol(lhs, model); if (lhsExpressionSymbol == null) { return; } var env = GetEnvironment(lhsExpressionSymbol, lhs, XmlTextReaderEnvironments, TempXmlTextReaderEnvironments); bool oldIsDtdProcessingDisabled = env.IsDtdProcessingDisabled; env.IsDtdProcessingDisabled = !SyntaxNodeHelper.NodeHasConstantValue(rhs, model, false); if (oldIsDtdProcessingDisabled && !env.IsDtdProcessingDisabled) { env.Definition = rhs; } } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsDtdProcessingProperty(symbol, XmlTypes)) { ISymbol lhsExpressionSymbol = SyntaxNodeHelper.GetSymbol(lhs, model); if (lhsExpressionSymbol == null) { return; } var env = GetEnvironment(lhsExpressionSymbol, lhs, XmlReaderSettingsEnvironments, TempXmlReaderSettingsEnvironments); bool oldIsDtdProcessingDisabled = env.IsDtdProcessingDisabled; env.IsDtdProcessingDisabled = !SyntaxNodeHelper.NodeHasConstantValue(rhs, model, 2 /*DtdProcessing.Parse*/); if (oldIsDtdProcessingDisabled && !env.IsDtdProcessingDisabled) { env.Definition = rhs; } } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsProhibitDtdProperty(symbol, XmlTypes)) { var lhsExpressionSymbol = SyntaxNodeHelper.GetSymbol(lhs, model); if (lhsExpressionSymbol == null) { return; } var env = GetEnvironment(lhsExpressionSymbol, lhs, XmlReaderSettingsEnvironments, TempXmlReaderSettingsEnvironments); bool oldIsDtdProcessingDisabled = env.IsDtdProcessingDisabled; env.IsDtdProcessingDisabled = !SyntaxNodeHelper.NodeHasConstantValue(rhs, model, false); if (oldIsDtdProcessingDisabled && !env.IsDtdProcessingDisabled) { env.Definition = rhs; } } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsMaxCharactersFromEntitiesProperty(symbol, XmlTypes)) { ISymbol lhsExpressionSymbol = SyntaxNodeHelper.GetSymbol(lhs, model); if (lhsExpressionSymbol == null) { return; } var env = GetEnvironment(lhsExpressionSymbol, lhs, XmlReaderSettingsEnvironments, TempXmlReaderSettingsEnvironments); //bool oldIsMaxCharactersFromEntitiesLimited = env.IsMaxCharactersFromEntitiesLimited; env.IsMaxCharactersFromEntitiesLimited = !SyntaxNodeHelper.NodeHasConstantValue(rhs, model, 0); //if (!env.IsMaxCharactersFromEntitiesLimited) // env.Definition = rhs; } }