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) ) ) ); } }
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) ) ) ); } }
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); XsltSettingsEnvironment env; // 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 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(DesktopAnalyzersResources.XslCompiledTransformLoadInsecureConstructedMessage) : nameof(DesktopAnalyzersResources.XslCompiledTransformLoadInsecureInputMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ); context.ReportDiagnostic( Diagnostic.Create( RuleDoNotUseInsecureXSLTScriptExecution, node.GetLocation(), message ) ); } } } }
private void AnalyzeNodeForXmlTextReaderDerivedTypeConstructorDecl(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.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(DesktopAnalyzersResources.XmlTextReaderDerivedClassConstructorNoSecureSettingsMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ) ) ); }
private void AnalyzeNodeForDtdProcessingOverloads(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; IMethodSymbol method = _syntaxNodeHelper.GetCalleeMethodSymbol(node, model); if (method == null) { return; } CompilationSecurityTypes xmlTypes = _xmlTypes; if (method.MatchMethodDerivedByName(xmlTypes.XmlDocument, SecurityMemberNames.Load) || //FxCop CA3056 method.MatchMethodDerivedByName(xmlTypes.XmlDocument, SecurityMemberNames.LoadXml) || //FxCop CA3057 method.MatchMethodDerivedByName(xmlTypes.XPathDocument, WellKnownMemberNames.InstanceConstructorName) || //FxCop CA3059 method.MatchMethodDerivedByName(xmlTypes.XmlSchema, SecurityMemberNames.Read) || //FxCop CA3060 method.MatchMethodDerivedByName(xmlTypes.DataSet, SecurityMemberNames.ReadXml) || //FxCop CA3063 method.MatchMethodDerivedByName(xmlTypes.DataSet, SecurityMemberNames.ReadXmlSchema) || //FxCop CA3064 method.MatchMethodDerivedByName(xmlTypes.XmlSerializer, SecurityMemberNames.Deserialize) || //FxCop CA3070 method.MatchMethodDerivedByName(xmlTypes.DataTable, SecurityMemberNames.ReadXml) || //FxCop CA3071 method.MatchMethodDerivedByName(xmlTypes.DataTable, SecurityMemberNames.ReadXmlSchema)) //FxCop CA3072 { if (SecurityDiagnosticHelpers.HasXmlReaderParameter(method, xmlTypes) < 0) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDTDProcessing; context.ReportDiagnostic( Diagnostic.Create( rule, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.DoNotUseDtdProcessingOverloadsMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model), method.Name) ) ); } } // We assume the design of derived type are secure, per Rule CA9003 else if (method.MatchMethodByName(xmlTypes.XmlDocument, WellKnownMemberNames.InstanceConstructorName)) { if (IsObjectConstructionForTemporaryObject(node)) // REVIEW: may be hard to check { bool isXmlDocumentSecureResolver = false; foreach (SyntaxNode arg in _syntaxNodeHelper.GetObjectInitializerExpressionNodes(node)) { SyntaxNode argLhs = _syntaxNodeHelper.GetAssignmentLeftNode(arg); SyntaxNode argRhs = _syntaxNodeHelper.GetAssignmentRightNode(arg); if (SecurityDiagnosticHelpers.IsXmlDocumentXmlResolverProperty(SyntaxNodeHelper.GetSymbol(argLhs, model), xmlTypes)) { if (!(SyntaxNodeHelper.NodeHasConstantValueNull(argRhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(argRhs).Type, xmlTypes))) { // if XmlResolver property is explicitly set to an insecure value in initializer list, // a warning would be generated when handling assignment of XmlDocument.XmlResolver // AnalyzeNodeForXmlDocument method, so we ignore it here. return; } else { isXmlDocumentSecureResolver = true; } } } if (!isXmlDocumentSecureResolver) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlDocumentWithNoSecureResolverMessage), _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model).Name) ); context.ReportDiagnostic(diag); } } } // We assume the design of derived type are secure, per Rule CA9003 else if (method.MatchMethodByName(xmlTypes.XmlTextReader, WellKnownMemberNames.InstanceConstructorName)) { if (IsObjectConstructionForTemporaryObject(node)) // REVIEW: may be hard to check { bool isXmlTextReaderSecureResolver, isXmlTextReaderDtdProcessingDisabled; isXmlTextReaderSecureResolver = isXmlTextReaderDtdProcessingDisabled = false; foreach (SyntaxNode arg in _syntaxNodeHelper.GetObjectInitializerExpressionNodes(node)) { SyntaxNode argLhs = _syntaxNodeHelper.GetAssignmentLeftNode(arg); SyntaxNode argRhs = _syntaxNodeHelper.GetAssignmentRightNode(arg); ISymbol symArgLhs = SyntaxNodeHelper.GetSymbol(argLhs, model); if (SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverProperty(symArgLhs, xmlTypes)) { if (!(SyntaxNodeHelper.NodeHasConstantValueNull(argRhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(argRhs).Type, xmlTypes))) { // Generate a warning whenever the XmlTextReader.XmlResolver property is set to an insecure value Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderSetInsecureResolutionMessage), _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model).Name ) ); context.ReportDiagnostic(diag); return; } else { isXmlTextReaderSecureResolver = true; } } else if (SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingProperty(symArgLhs, xmlTypes)) { if (SyntaxNodeHelper.GetSymbol(argRhs, model).MatchFieldByName(xmlTypes.DtdProcessing, SecurityMemberNames.Parse)) { // Generate a warning whenever the XmlTextReader.DtdProcessing property is set to DtdProcessing.Parse Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderSetInsecureResolutionMessage), _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model).Name ) ); context.ReportDiagnostic(diag); return; } else { isXmlTextReaderDtdProcessingDisabled = true; } } } if (!isXmlTextReaderSecureResolver || !isXmlTextReaderDtdProcessingDisabled) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderConstructedWithNoSecureResolutionMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ) ); context.ReportDiagnostic(diag); } } } else if (method.MatchMethodDerivedByName(xmlTypes.XmlReader, SecurityMemberNames.Create)) { int xmlReaderSettingsIndex = SecurityDiagnosticHelpers.HasXmlReaderSettingsParameter(method, xmlTypes); if (xmlReaderSettingsIndex < 0) //FxCop CA3053:XmlReaderCreateWrongOverload { DiagnosticDescriptor rule = RuleDoNotUseInsecureDTDProcessing; context.ReportDiagnostic( Diagnostic.Create( rule, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlReaderCreateWrongOverloadMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ) ) ); } else { SyntaxNode settingsNode = _syntaxNodeHelper.GetInvocationArgumentExpressionNodes(node).ElementAt(xmlReaderSettingsIndex); ISymbol settingsSymbol = SyntaxNodeHelper.GetSymbol(settingsNode, model); XmlReaderSettingsEnvironment env = null; if (!_xmlReaderSettingsEnvironments.TryGetValue(settingsSymbol, out env)) { // symbol for settings is not found => passed in without any change => assume insecure Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlReaderCreateInsecureInputMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ) ); context.ReportDiagnostic(diag); } else if (!env.IsDtdProcessingDisabled && !(env.IsSecureResolver & env.IsMaxCharactersFromEntitiesLimited)) { Diagnostic diag; if (env.IsConstructedInCodeBlock) { diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlReaderCreateInsecureConstructedMessage) ) ); } else { diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlReaderCreateInsecureInputMessage) ) ); } context.ReportDiagnostic(diag); } } } }