private void AnalyzeMethodOverloads(OperationAnalysisContext context, IMethodSymbol method, ImmutableArray <IArgumentOperation> arguments, SyntaxNode expressionSyntax) { 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) { context.ReportDiagnostic(expressionSyntax.CreateDiagnostic(RuleDoNotUseDtdProcessingOverloads, method.Name)); } } else if (method.MatchMethodDerivedByName(_xmlTypes.XmlReader, SecurityMemberNames.Create)) { int xmlReaderSettingsIndex = SecurityDiagnosticHelpers.GetXmlReaderSettingsParameterIndex(method, _xmlTypes); if (xmlReaderSettingsIndex < 0) { if (method.Parameters.Length == 1 && method.Parameters[0].RefKind == RefKind.None && method.Parameters[0].Type.SpecialType == SpecialType.System_String) { // inputUri can load be a URL. Should further investigate if this is worth flagging. context.ReportDiagnostic(expressionSyntax.CreateDiagnostic(RuleXmlReaderCreateWrongOverload)); } // If no XmlReaderSettings are passed, then the default // XmlReaderSettings are used, with DtdProcessing set to Prohibit. } else if (arguments.Length > xmlReaderSettingsIndex) { IArgumentOperation arg = arguments[xmlReaderSettingsIndex]; ISymbol settingsSymbol = arg.GetReferencedMemberOrLocalOrParameter(); if (settingsSymbol == null) { return; } // If we have no XmlReaderSettingsEnvironment, then we don't know. if (_xmlReaderSettingsEnvironments.TryGetValue(settingsSymbol, out XmlReaderSettingsEnvironment env) && !env.IsDtdProcessingDisabled && !(env.IsSecureResolver && env.IsMaxCharactersFromEntitiesLimited)) { var diag = env.IsConstructedInCodeBlock ? expressionSyntax.CreateDiagnostic(RuleXmlReaderCreateInsecureConstructed) : expressionSyntax.CreateDiagnostic(RuleXmlReaderCreateInsecureInput); context.ReportDiagnostic(diag); } } } }
private void AnalyzeMethodOverloads(OperationAnalysisContext context, IMethodSymbol method, ImmutableArray <IArgumentOperation> arguments, SyntaxNode expressionSyntax) { 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, expressionSyntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.DoNotUseDtdProcessingOverloadsMessage), method.Name ) ) ); } } else if (method.MatchMethodDerivedByName(_xmlTypes.XmlReader, SecurityMemberNames.Create)) { int xmlReaderSettingsIndex = SecurityDiagnosticHelpers.GetXmlReaderSettingsParameterIndex(method, _xmlTypes); if (xmlReaderSettingsIndex < 0) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessing; Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, expressionSyntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlReaderCreateWrongOverloadMessage) ) ); context.ReportDiagnostic(diag); } else { SemanticModel model = context.Compilation.GetSemanticModel(context.Operation.Syntax.SyntaxTree); IArgumentOperation arg = arguments[xmlReaderSettingsIndex]; ISymbol settingsSymbol = arg.Value.Syntax.GetDeclaredOrReferencedSymbol(model); if (settingsSymbol == null) { return; } if (!_xmlReaderSettingsEnvironments.TryGetValue(settingsSymbol, out XmlReaderSettingsEnvironment env)) { // symbol for settings is not found => passed in without any change => assume insecure Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, expressionSyntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlReaderCreateInsecureInputMessage) ) ); context.ReportDiagnostic(diag); } else if (!env.IsDtdProcessingDisabled && !(env.IsSecureResolver && env.IsMaxCharactersFromEntitiesLimited)) { Diagnostic diag; if (env.IsConstructedInCodeBlock) { diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, expressionSyntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlReaderCreateInsecureConstructedMessage) ) ); } else { diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, expressionSyntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlReaderCreateInsecureInputMessage) ) ); } context.ReportDiagnostic(diag); } } } }
protected void AnalyzeInvocation(SyntaxNode node, SemanticModel model, Action <Diagnostic> reportDiagnostic) { IMethodSymbol method = SyntaxNodeHelper.GetCalleeMethodSymbol(node, model); if (method == null) { return; } if (method.MatchMethodByName(XmlTypes.XmlSchema, "Read")) { if (!AreDefaultsSecure && SecurityDiagnosticHelpers.GetSpecifiedParameterIndex(method, XmlTypes, SecurityDiagnosticHelpers.IsXmlReaderType) < 0) { var diag = Diagnostic.Create(XxeDiagnosticAnalyzer.Rule, node.GetLocation()); reportDiagnostic(diag); } } else if (method.MatchMethodDerivedByName(XmlTypes.XmlReader, "Create")) { int xmlReaderSettingsIndex = SecurityDiagnosticHelpers.GetXmlReaderSettingsParameterIndex(method, XmlTypes); if (xmlReaderSettingsIndex < 0) { return; } SyntaxNode settingsNode = SyntaxNodeHelper.GetInvocationArgumentExpressionNodes(node).ElementAt(xmlReaderSettingsIndex); XmlReaderSettingsEnvironment env; if (SyntaxNodeHelper.IsObjectConstructionForTemporaryObject(settingsNode)) { OjectCreationOperationsAnalyzed.Add(settingsNode); env = AnalyzeObjectCreationForXmlReaderSettings(settingsNode, model); TempXmlReaderSettingsEnvironments[settingsNode] = env; } else { ISymbol settingsSymbol = SyntaxNodeHelper.GetSymbol(settingsNode, model); XmlReaderSettingsEnvironments.TryGetValue(settingsSymbol, out env); } if (env == null) { // symbol for settings is not found => passed in without any change => assume insecure reportDiagnostic(Diagnostic.Create(XxeDiagnosticAnalyzer.Rule, node.GetLocation())); } } else if (ReferenceEquals(method.ContainingType, XmlTypes.ConfigXmlDocument)) { var variableNode = SyntaxNodeHelper.GetMemberAccessExpressionNode(SyntaxNodeHelper.GetInvocationExpressionNode(node)); if (variableNode == null) { throw new ArgumentException(nameof(variableNode)); } var variableSymbol = SyntaxNodeHelper.GetSymbol(variableNode, model); if (variableSymbol == null) { return; } XmlDocumentEnvironment env; if (SyntaxNodeHelper.IsObjectConstructionForTemporaryObject(variableNode)) { OjectCreationOperationsAnalyzed.Add(variableNode); env = AnalyzeObjectCreationForXmlDocument(variableSymbol, variableNode, model); TempXmlDocumentEnvironments[variableNode] = env; } else { XmlDocumentEnvironments.TryGetValue(variableSymbol, out env); } if (method.MatchMethodDerivedByName(XmlTypes.ConfigXmlDocument, "Load")) { if (env != null) { env.WasSafeFunctionCalled = true; } } else { if (env == null) { // symbol not found => passed in without any change => assume insecure reportDiagnostic(Diagnostic.Create(XxeDiagnosticAnalyzer.Rule, node.GetLocation())); } else { env.WasSomethingElseCalled = true; } } } else if (ReferenceEquals(method.ContainingType, XmlTypes.XmlDocument)) { var variableNode = SyntaxNodeHelper.GetMemberAccessExpressionNode(SyntaxNodeHelper.GetInvocationExpressionNode(node)); if (variableNode == null) { throw new ArgumentException(nameof(variableNode)); } var variableSymbol = SyntaxNodeHelper.GetSymbol(variableNode, model); if (variableSymbol == null) { return; } XmlDocumentEnvironment env; if (SyntaxNodeHelper.IsObjectConstructionForTemporaryObject(variableNode)) { OjectCreationOperationsAnalyzed.Add(variableNode); env = AnalyzeObjectCreationForXmlDocument(variableSymbol, variableNode, model); TempXmlDocumentEnvironments[variableNode] = env; } else { XmlDocumentEnvironments.TryGetValue(variableSymbol, out env); } // Special case XmlDataDocument.LoadXml throws NotSupportedException if (env == null || !ReferenceEquals(env.Type, XmlTypes.XmlDataDocument)) { return; } // LoadXml is not overridden in XmlDataDocument, thus XmlTypes.XmlDocument if (method.MatchMethodDerivedByName(XmlTypes.XmlDocument, "LoadXml")) { env.WasSafeFunctionCalled = true; } else { env.WasSomethingElseCalled = true; } } }
private void AnalyzeMethodOverloads(OperationAnalysisContext context, IMethodSymbol method, ImmutableArray <IArgumentOperation> arguments, SyntaxNode expressionSyntax) { 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, expressionSyntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.DoNotUseDtdProcessingOverloadsMessage), method.Name ) ) ); } } else if (method.MatchMethodDerivedByName(_xmlTypes.XmlReader, SecurityMemberNames.Create)) { int xmlReaderSettingsIndex = SecurityDiagnosticHelpers.GetXmlReaderSettingsParameterIndex(method, _xmlTypes); if (xmlReaderSettingsIndex < 0) { if (method.Parameters.Length == 1 && method.Parameters[0].RefKind == RefKind.None && method.Parameters[0].Type.SpecialType == SpecialType.System_String) { // inputUri can load be a URL. Should further investigate if this is worth flagging. Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, expressionSyntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlReaderCreateWrongOverloadMessage) ) ); context.ReportDiagnostic(diag); } // If no XmlReaderSettings are passed, then the default // XmlReaderSettings are used, with DtdProcessing set to Prohibit. } else { SemanticModel model = context.Compilation.GetSemanticModel(context.Operation.Syntax.SyntaxTree); IArgumentOperation arg = arguments[xmlReaderSettingsIndex]; ISymbol settingsSymbol = arg.Value.Syntax.GetDeclaredOrReferencedSymbol(model); if (settingsSymbol == null) { return; } // If we have no XmlReaderSettingsEnvironment, then we don't know. if (_xmlReaderSettingsEnvironments.TryGetValue(settingsSymbol, out XmlReaderSettingsEnvironment env) && !env.IsDtdProcessingDisabled && !(env.IsSecureResolver && env.IsMaxCharactersFromEntitiesLimited)) { Diagnostic diag; if (env.IsConstructedInCodeBlock) { diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, expressionSyntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlReaderCreateInsecureConstructedMessage) ) ); } else { diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, expressionSyntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlReaderCreateInsecureInputMessage) ) ); } context.ReportDiagnostic(diag); } } } }