private XmlReaderSettingsEnvironment AnalyzeObjectCreationForXmlReaderSettings(SyntaxNode node, SemanticModel model) { var env = new XmlReaderSettingsEnvironment(AreDefaultsSecure, XmlTypes.XmlReaderSettings, node); foreach (SyntaxNode arg in SyntaxNodeHelper.GetObjectInitializerExpressionNodes(node)) { SyntaxNode argLhs = SyntaxNodeHelper.GetAssignmentLeftNode(arg); SyntaxNode argRhs = SyntaxNodeHelper.GetAssignmentRightNode(arg); ISymbol argLhsSymbol = SyntaxNodeHelper.GetSymbol(argLhs, model); if (SecurityDiagnosticHelpers.IsXmlReaderSettingsXmlResolverProperty(SyntaxNodeHelper.GetSymbol(argLhs, model), XmlTypes)) { env.IsSecureResolver = SyntaxNodeHelper.NodeHasConstantValueNull(argRhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(argRhs).Type, XmlTypes); } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsDtdProcessingProperty(argLhsSymbol, XmlTypes)) { env.IsDtdProcessingDisabled = !SyntaxNodeHelper.NodeHasConstantValue(argRhs, model, 2 /*DtdProcessing.Parse*/); } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsProhibitDtdProperty(argLhsSymbol, XmlTypes)) { env.IsDtdProcessingDisabled = !SyntaxNodeHelper.NodeHasConstantValue(argRhs, model, false); } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsMaxCharactersFromEntitiesProperty(argLhsSymbol, XmlTypes)) { env.IsMaxCharactersFromEntitiesLimited = !SyntaxNodeHelper.NodeHasConstantValue(argRhs, model, 0); } } return(env); }
private void AnalyzeObjectCreationInternal(OperationAnalysisContext context, ISymbol variable, IOperation valueOpt) { IObjectCreationOperation objCreation = valueOpt as IObjectCreationOperation; if (objCreation == null) { return; } if (_objectCreationOperationsAnalyzed.Contains(objCreation)) { return; } else { _objectCreationOperationsAnalyzed.Add(objCreation); } if (SecurityDiagnosticHelpers.IsXmlDocumentCtorDerived(objCreation.Constructor, _xmlTypes)) { AnalyzeObjectCreationForXmlDocument(context, variable, objCreation); } else if (SecurityDiagnosticHelpers.IsXmlTextReaderCtorDerived(objCreation.Constructor, _xmlTypes)) { AnalyzeObjectCreationForXmlTextReader(context, variable, objCreation); } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsCtor(objCreation.Constructor, _xmlTypes)) { AnalyzeObjectCreationForXmlReaderSettings(context, variable, objCreation); } else { AnalyzeMethodOverloads(context, objCreation.Constructor, objCreation.Arguments, objCreation.Syntax); } }
private XmlTextReaderEnvironment AnalyzeObjectCreationForXmlTextReader(IMethodSymbol symbol, SyntaxNode node, SemanticModel model) { var env = new XmlTextReaderEnvironment(AreDefaultsSecure, symbol, node); if (!ReferenceEquals(symbol.ContainingType, XmlTypes.XmlTextReader)) { // We assume the design of derived type is secure env.IsDtdProcessingDisabled = true; env.IsSecureResolver = true; } foreach (SyntaxNode arg in SyntaxNodeHelper.GetObjectInitializerExpressionNodes(node)) { SyntaxNode argLhs = SyntaxNodeHelper.GetAssignmentLeftNode(arg); SyntaxNode argRhs = SyntaxNodeHelper.GetAssignmentRightNode(arg); ISymbol argLhsSymbol = SyntaxNodeHelper.GetSymbol(argLhs, model); if (SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverPropertyDerived(argLhsSymbol, XmlTypes)) { env.IsSecureResolver = SyntaxNodeHelper.NodeHasConstantValueNull(argRhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(argRhs).Type, XmlTypes); } else if (SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingPropertyDerived(argLhsSymbol, XmlTypes)) { env.IsDtdProcessingDisabled = !SyntaxNodeHelper.NodeHasConstantValue(argRhs, model, 2 /*DtdProcessing.Parse*/); } else if (SecurityDiagnosticHelpers.IsXmlTextReaderProhibitDtdPropertyDerived(argLhsSymbol, XmlTypes)) { env.IsDtdProcessingDisabled = !SyntaxNodeHelper.NodeHasConstantValue(argRhs, model, false); } } return(env); }
public override void Initialize(AnalysisContext analysisContext) { // TODO: Make analyzer thread-safe //analysisContext.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics in generated code. analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); analysisContext.RegisterCompilationStartAction( (context) => { Compilation compilation = context.Compilation; var xmlTypes = new CompilationSecurityTypes(compilation); if (ReferencesAnyTargetType(xmlTypes)) { Version version = SecurityDiagnosticHelpers.GetDotNetFrameworkVersion(compilation); if (version != null) { context.RegisterOperationBlockStartAction( (c) => { RegisterAnalyzer(c, xmlTypes, version); }); } } }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics in generated code. context.ConfigureGeneratedCodeAnalysis( GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction(context => { Compilation compilation = context.Compilation; var xmlTypes = new CompilationSecurityTypes(compilation); if (ReferencesAnyTargetType(xmlTypes)) { var version = SecurityDiagnosticHelpers.GetDotNetFrameworkVersion(compilation); // bail if we are not analyzing project targeting .NET Framework // TODO: should we throw an exception to notify user? if (version != null) { SymbolAndNodeAnalyzer analyzer = new SymbolAndNodeAnalyzer(xmlTypes, version); context.RegisterSymbolAction(analyzer.AnalyzeSymbol, SymbolKind.NamedType); context.RegisterOperationBlockStartAction(analyzer.AnalyzeOperationBlock); } } }); }
public override void Initialize(AnalysisContext analysisContext) #pragma warning restore RS1026 // Enable concurrent execution { // TODO: Make analyzer thread-safe. //analysisContext.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics in generated code. analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); analysisContext.RegisterCompilationStartAction( (context) => { Compilation compilation = context.Compilation; var xmlTypes = new CompilationSecurityTypes(compilation); if (ReferencesAnyTargetType(xmlTypes)) { Version version = SecurityDiagnosticHelpers.GetDotNetFrameworkVersion(compilation); // bail if we are not analyzing project targeting .NET Framework // TODO: should we throw an exception to notify user? if (version != null) { SymbolAndNodeAnalyzer analyzer = GetAnalyzer(context, xmlTypes, version); context.RegisterSymbolAction(analyzer.AnalyzeSymbol, SymbolKind.NamedType); } } }); }
private XmlDocumentEnvironment AnalyzeObjectCreationForXmlDocument(ISymbol symbol, SyntaxNode node, SemanticModel model) { var env = new XmlDocumentEnvironment(AreDefaultsSecure, symbol.ContainingType, node); if (!ReferenceEquals(symbol.ContainingType, XmlTypes.XmlDocument) && !ReferenceEquals(symbol.ContainingType, XmlTypes.XmlDataDocument) && !ReferenceEquals(symbol.ContainingType, XmlTypes.ConfigXmlDocument) && !ReferenceEquals(symbol.ContainingType, XmlTypes.XmlFileInfoDocument) && !ReferenceEquals(symbol.ContainingType, XmlTypes.XmlTransformableDocument)) { // We assume the design of derived type is secure env.IsSecureResolver = true; } foreach (SyntaxNode arg in SyntaxNodeHelper.GetObjectInitializerExpressionNodes(node)) { SyntaxNode argLhs = SyntaxNodeHelper.GetAssignmentLeftNode(arg); SyntaxNode argRhs = SyntaxNodeHelper.GetAssignmentRightNode(arg); if (!SecurityDiagnosticHelpers.IsXmlDocumentXmlResolverPropertyDerived(SyntaxNodeHelper.GetSymbol(argLhs, model), XmlTypes)) { continue; } env.IsSecureResolver = SyntaxNodeHelper.NodeHasConstantValueNull(argRhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(argRhs).Type, XmlTypes); break; } return(env); }
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 AnalyzeObjectCreationForXmlTextReader(OperationAnalysisContext context, ISymbol variable, IObjectCreationOperation objCreation) { if (variable == null || !_xmlTextReaderEnvironments.TryGetValue(variable, out XmlTextReaderEnvironment env)) { env = new XmlTextReaderEnvironment(_isFrameworkSecure) { XmlTextReaderDefinition = objCreation.Syntax }; } if (objCreation.Constructor.ContainingType != _xmlTypes.XmlTextReader) { env.IsDtdProcessingDisabled = true; env.IsSecureResolver = true; } 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 (propValue is IConversionOperation operation && SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverPropertyDerived(prop, _xmlTypes)) { env.IsXmlResolverSet = true; if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { env.IsSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { env.IsSecureResolver = true; } else { env.IsSecureResolver = false; } } else if (SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingPropertyDerived(prop, _xmlTypes)) { env.IsDtdProcessingSet = true; env.IsDtdProcessingDisabled = !SecurityDiagnosticHelpers.IsExpressionEqualsDtdProcessingParse(propValue); } } } }
private static DiagnosticDescriptor CreateDiagnosticDescriptor(LocalizableResourceString messageFormat, LocalizableResourceString description) { return(DiagnosticDescriptorHelper.Create(RuleId, SecurityDiagnosticHelpers.GetLocalizableResourceString(nameof(MicrosoftNetFrameworkAnalyzersResources.InsecureDtdProcessingInApiDesign)), messageFormat, DiagnosticCategory.Security, RuleLevel.IdeHidden_BulkConfigurable, description, isPortedFxCopRule: false, isDataflowRule: false)); }
private static DiagnosticDescriptor CreateDiagnosticDescriptor(LocalizableResourceString messageFormat, LocalizableResourceString description) { return(DiagnosticDescriptorHelper.Create(RuleId, SecurityDiagnosticHelpers.GetLocalizableResourceString(nameof(MicrosoftNetFrameworkAnalyzersResources.InsecureXsltScriptProcessingMessage)), messageFormat, DiagnosticCategory.Security, RuleLevel.BuildWarning, description, isPortedFxCopRule: false, isDataflowRule: false)); }
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) { // 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 bool isTargetProperty)) { break; } } if (!hasSetSecureXmlResolver) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessingInApiDesign; context.ReportDiagnostic( CreateDiagnostic( methodSymbol.Locations, rule, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlDocumentDerivedClassConstructorNoSecureXmlResolverMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ) ) ); } }
private static DiagnosticDescriptor CreateDiagnosticDescriptor(LocalizableResourceString messageFormat, LocalizableResourceString description, string helpLink = null) { return(new DiagnosticDescriptor(RuleId, SecurityDiagnosticHelpers.GetLocalizableResourceString(nameof(MicrosoftNetFrameworkAnalyzersResources.InsecureDtdProcessingInApiDesign)), messageFormat, DiagnosticCategory.Security, DiagnosticHelpers.DefaultDiagnosticSeverity, isEnabledByDefault: DiagnosticHelpers.EnabledByDefaultIfNotBuildingVSIX, description: description, helpLinkUri: helpLink, customTags: WellKnownDiagnosticTags.Telemetry)); }
// Local functions static void ReportDiagnostic(SyntaxNode node, OperationAnalysisContext context) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlDocumentWithNoSecureResolverMessage) ) ); context.ReportDiagnostic(diag); }
// 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; if (!(SyntaxNodeHelper.GetDeclaredSymbol(node, model) is IMethodSymbol methodSymbol) || // 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; } IEnumerable <SyntaxNode> assignments = _syntaxNodeHelper.GetDescendantAssignmentExpressionNodes(node); foreach (SyntaxNode assignment in assignments) { // this is intended to be an assignment, not a bug if (IsAssigningIntendedValueToPropertyDerivedFromType(assignment, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlDocumentXmlResolverProperty(s, _xmlTypes)); }, (n) => { return(!(SyntaxNodeHelper.NodeHasConstantValueNull(n, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(n).Type, _xmlTypes))); }, out bool isTargetProperty) ) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessingInApiDesign; context.ReportDiagnostic( CreateDiagnostic( assignment.GetLocation(), rule, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlDocumentDerivedClassSetInsecureXmlResolverInMethodMessage), methodSymbol.Name ) ) ); } } }
private void AnalyzeObjectCreationForXmlTextReader(OperationAnalysisContext context, ISymbol variable, IObjectCreationExpression objCreation) { if (variable == null || !_xmlTextReaderEnvironments.TryGetValue(variable, out XmlTextReaderEnvironment env)) { env = new XmlTextReaderEnvironment(_isFrameworkSecure) { XmlTextReaderDefinition = objCreation.Syntax }; } if (objCreation.Constructor.ContainingType != _xmlTypes.XmlTextReader) { env.IsDtdProcessingDisabled = true; env.IsSecureResolver = true; } foreach (ISymbolInitializer init in objCreation.MemberInitializers) { if (init is IPropertyInitializer prop) { if (prop.Value is IConversionExpression operation && SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverPropertyDerived(prop.InitializedProperty, _xmlTypes)) { env.IsXmlResolverSet = true; if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { env.IsSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { env.IsSecureResolver = true; } else { env.IsSecureResolver = false; } } else if (SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingPropertyDerived(prop.InitializedProperty, _xmlTypes)) { env.IsDtdProcessingSet = true; env.IsDtdProcessingDisabled = !SecurityDiagnosticHelpers.IsExpressionEqualsDtdProcessingParse(prop.Value); } } }
private T GetEnvironment <T>(ISymbol symbol, SyntaxNode node, Dictionary <ISymbol, T> permanentEnvironments, Dictionary <SyntaxNode, T> temporaryEnvironments) { if (permanentEnvironments.TryGetValue(symbol, out var env)) { return(env); } if (temporaryEnvironments.TryGetValue(node, out env)) { return(env); } // external symbol or class member, assume defaults env = (T)Activator.CreateInstance(typeof(T), AreDefaultsSecure, SecurityDiagnosticHelpers.GetTypeSymbol(symbol), node); permanentEnvironments[symbol] = env; return(env); }
private void AnalyzeSymbolForXmlTextReaderDerivedType(SymbolAnalysisContext context) { ISymbol symbol = context.Symbol; if (symbol.Kind != SymbolKind.NamedType) { return; } var typeSymbol = (INamedTypeSymbol)symbol; INamedTypeSymbol xmlTextReaderSym = _xmlTypes.XmlTextReader; if ((!Equals(typeSymbol, xmlTextReaderSym)) && typeSymbol.DerivesFrom(xmlTextReaderSym, baseTypesOnly: true)) { bool explicitlyDeclared = true; if (typeSymbol.Constructors.Length == 1) { IMethodSymbol constructor = typeSymbol.Constructors[0]; explicitlyDeclared = !constructor.IsImplicitlyDeclared; if (!explicitlyDeclared && !_isFrameworkSecure) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessingInApiDesign; context.ReportDiagnostic( CreateDiagnostic( typeSymbol.Locations, rule, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlTextReaderDerivedClassNoConstructorMessage), symbol.Name ) ) ); } } _xmlTextReaderDerivedTypes.AddOrUpdate(typeSymbol, explicitlyDeclared, (k, v) => explicitlyDeclared); } }
public void AnalyzeOperationBlock(OperationBlockAnalysisContext context) { foreach (KeyValuePair <ISymbol, XmlDocumentEnvironment> p in _xmlDocumentEnvironments) { XmlDocumentEnvironment env = p.Value; if (!(env.IsXmlResolverSet | env.IsSecureResolver)) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, env.XmlDocumentDefinition.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlDocumentWithNoSecureResolverMessage) ) ); context.ReportDiagnostic(diag); } } foreach (KeyValuePair <ISymbol, XmlTextReaderEnvironment> p in _xmlTextReaderEnvironments) { XmlTextReaderEnvironment env = p.Value; if (!(env.IsXmlResolverSet | env.IsSecureResolver) || !(env.IsDtdProcessingSet | env.IsDtdProcessingDisabled)) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, env.XmlTextReaderDefinition.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlTextReaderConstructedWithNoSecureResolutionMessage) ) ); 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; } } }
protected void AnalyzeObjectCreation(ISymbol variableSymbol, SyntaxNode objectCreationNode, SemanticModel model, Action <Diagnostic> reportDiagnostic) { if (!(SyntaxNodeHelper.GetSymbol(objectCreationNode, model) is IMethodSymbol symbol)) { return; } if (OjectCreationOperationsAnalyzed.Contains(objectCreationNode)) { return; } OjectCreationOperationsAnalyzed.Add(objectCreationNode); if (SecurityDiagnosticHelpers.IsXmlDocumentCtorDerived(symbol, XmlTypes)) { var env = AnalyzeObjectCreationForXmlDocument(symbol, objectCreationNode, model); if (variableSymbol != null) { XmlDocumentEnvironments[variableSymbol] = env; } else { TempXmlDocumentEnvironments[objectCreationNode] = env; } } else if (SecurityDiagnosticHelpers.IsXmlTextReaderCtorDerived(symbol, XmlTypes)) { var env = AnalyzeObjectCreationForXmlTextReader(symbol, objectCreationNode, model); if (variableSymbol != null) { XmlTextReaderEnvironments[variableSymbol] = env; } else { TempXmlTextReaderEnvironments[objectCreationNode] = env; } } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsCtor(symbol, XmlTypes)) { var env = AnalyzeObjectCreationForXmlReaderSettings(objectCreationNode, model); if (variableSymbol != null) { XmlReaderSettingsEnvironments[variableSymbol] = env; } else { TempXmlReaderSettingsEnvironments[objectCreationNode] = env; } } else if (symbol.MatchMethodByName(XmlTypes.XPathDocument, WellKnownMemberNames.InstanceConstructorName)) { if (AreDefaultsSecure) { return; } var diag = Diagnostic.Create(XxeDiagnosticAnalyzer.Rule, objectCreationNode.GetLocation()); reportDiagnostic(diag); } }
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); } } } }
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) ) ) ); }
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 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 { context.ReportDiagnostic(assign.Syntax.CreateDiagnostic(RuleXmlDocumentWithNoSecureResolver)); return; } } else { AnalyzeNeverSetProperties(context, prop, assign.Syntax.GetLocation()); } } } } xmlDocumentEnvironment.IsSecureResolver = isXmlDocumentSecureResolver; if (variable != null) { _xmlDocumentEnvironments[variable] = xmlDocumentEnvironment; } else if (!xmlDocumentEnvironment.IsSecureResolver) // Insecure temp object { context.ReportDiagnostic(node.CreateDiagnostic(RuleXmlDocumentWithNoSecureResolver)); } 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 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; } }
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 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); } } } }