public sealed override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

            // Security analyzer - analyze and report diagnostics on generated code.
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                Compilation?compilation = compilationStartAnalysisContext.Compilation;
                WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation);

                if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemDataDataSet,
                        out INamedTypeSymbol? dataSetTypeSymbol) ||
                    !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemDataDataTable,
                        out INamedTypeSymbol? dataTableTypeSymbol))
                {
                    return;
                }

                INamedTypeSymbol?dataContractSerializerTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemRuntimeSerializationDataContractSerializer);
                INamedTypeSymbol?dataContractJsonSerializerTypeSymbol =
                    wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemRuntimeSerializationJsonDataContractJsonSerializer);
                INamedTypeSymbol?javaScriptSerializerTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemWebScriptSerializationJavaScriptSerializer);
                INamedTypeSymbol?typeTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemType);
                INamedTypeSymbol?xmlSerializerTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemXmlSerializationXmlSerializer);
                INamedTypeSymbol?jsonNetJsonSerializerTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.NewtonsoftJsonJsonSerializer);
                INamedTypeSymbol?jsonNetJsonConvertTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.NewtonsoftJsonJsonConvert);

                if (dataContractSerializerTypeSymbol == null &&
                    dataContractJsonSerializerTypeSymbol == null &&
                    javaScriptSerializerTypeSymbol == null &&
                    xmlSerializerTypeSymbol == null &&
                    jsonNetJsonSerializerTypeSymbol == null &&
                    jsonNetJsonConvertTypeSymbol == null)
                {
                    return;
                }

                InsecureDeserializationTypeDecider decider = InsecureDeserializationTypeDecider.GetOrCreate(compilation);

                compilationStartAnalysisContext.RegisterOperationAction(
                    (OperationAnalysisContext operationAnalysisContext) =>
                {
                    IInvocationOperation invocationOperation =
                        (IInvocationOperation)operationAnalysisContext.Operation;
                    if (!IsDeserializationMethod(
                            invocationOperation,
                            out ObjectGraphOptions? optionsToUse,
                            out IEnumerable <(ITypeSymbol DeserializedTypeSymbol, IOperation OperationForLocation)>?deserializedTypes))
                    {
                        return;
                    }

                    RoslynDebug.Assert(optionsToUse != null);
                    RoslynDebug.Assert(deserializedTypes != null);

                    ReportDiagnosticsForInsecureTypes(operationAnalysisContext, optionsToUse, deserializedTypes);
                },
                    OperationKind.Invocation);

                compilationStartAnalysisContext.RegisterOperationAction(
                    (OperationAnalysisContext operationAnalysisContext) =>
                {
                    IObjectCreationOperation objectCreationOperation =
                        (IObjectCreationOperation)operationAnalysisContext.Operation;
                    if (!IsDeserializationConstructor(
                            objectCreationOperation,
                            out ObjectGraphOptions? optionsToUse,
                            out IEnumerable <(ITypeSymbol DeserializedTypeSymbol, IOperation OperationForLocation)>?deserializedTypes))
                    {
                        return;
                    }

                    RoslynDebug.Assert(optionsToUse != null);
                    RoslynDebug.Assert(deserializedTypes != null);

                    ReportDiagnosticsForInsecureTypes(operationAnalysisContext, optionsToUse, deserializedTypes);
                },
                    OperationKind.ObjectCreation);

                return;

                // Local functions.

                // Determines if the invoked method is for deserialization, and what type of deserialization.
                bool IsDeserializationMethod(
                    IInvocationOperation invocationOperation,
                    out ObjectGraphOptions? optionsToUse,
                    out IEnumerable <(ITypeSymbol DeserializedTypeSymbol, IOperation OperationForLocation)>?deserializedTypes)
                {
                    optionsToUse      = null;
                    deserializedTypes = null;

                    IMethodSymbol targetMethod = invocationOperation.TargetMethod;
                    if (invocationOperation.Instance?.Type?.DerivesFrom(javaScriptSerializerTypeSymbol) == true)
                    {
                        if (targetMethod.MetadataName == "DeserializeObject" &&
                            invocationOperation.Parent?.Kind == OperationKind.Conversion &&
                            invocationOperation.Parent is IConversionOperation javaScriptConversionOperation)
                        {
                            optionsToUse      = ObjectGraphOptions.JavaScriptSerializerOptions;
                            deserializedTypes = new[]
                            {
                                (javaScriptConversionOperation.Type, (IOperation)javaScriptConversionOperation)
                            };
                        }
Exemplo n.º 2
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

            // Security analyzer - analyze and report diagnostics on generated code.
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                Compilation?compilation = compilationStartAnalysisContext.Compilation;
                WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation);

                if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemDataDataSet,
                        out INamedTypeSymbol? dataSetTypeSymbol) ||
                    !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemDataDataTable,
                        out INamedTypeSymbol? dataTableTypeSymbol))
                {
                    return;
                }

                INamedTypeSymbol?webMethodAttributeTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemWebServicesWebMethodAttribute);
                INamedTypeSymbol?operationContractAttributeTypeSymbol =
                    wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemServiceModelOperationContractAttribute);

                if (webMethodAttributeTypeSymbol == null && operationContractAttributeTypeSymbol == null)
                {
                    return;
                }

                InsecureDeserializationTypeDecider decider = InsecureDeserializationTypeDecider.GetOrCreate(compilation);

                // Symbol actions for SymbolKind.Method don't seem to trigger on interface methods, so we'll do register
                // for SymbolKind.NamedTypeSymbol instead.
                compilationStartAnalysisContext.RegisterSymbolAction(
                    (SymbolAnalysisContext symbolAnalysisContext) =>
                {
                    INamedTypeSymbol namedTypeSymbol = (INamedTypeSymbol)symbolAnalysisContext.Symbol;
                    if (namedTypeSymbol.TypeKind != TypeKind.Interface &&
                        namedTypeSymbol.TypeKind != TypeKind.Class)
                    {
                        return;
                    }

                    foreach (ISymbol?memberSymbol in namedTypeSymbol.GetMembers())
                    {
                        if (!(memberSymbol is IMethodSymbol methodSymbol))
                        {
                            continue;
                        }

                        ObjectGraphOptions optionsToUse;
                        if (methodSymbol.HasAttribute(webMethodAttributeTypeSymbol))
                        {
                            optionsToUse = ObjectGraphOptions.XmlSerializerOptions;
                        }
                        else if (methodSymbol.HasAttribute(operationContractAttributeTypeSymbol))
                        {
                            optionsToUse = ObjectGraphOptions.DataContractOptions;
                        }
                        else
                        {
                            continue;
                        }

                        foreach (IParameterSymbol parameterSymbol in methodSymbol.Parameters)
                        {
                            if (decider.IsObjectGraphInsecure(
                                    parameterSymbol.Type,
                                    optionsToUse,
                                    out ImmutableArray <InsecureObjectGraphResult> results))
                            {
                                foreach (InsecureObjectGraphResult result in results)
                                {
                                    symbolAnalysisContext.ReportDiagnostic(
                                        Diagnostic.Create(
                                            ObjectGraphContainsDangerousTypeDescriptor,
                                            parameterSymbol.DeclaringSyntaxReferences.First().GetSyntax().GetLocation(),
                                            result.InsecureType.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
                                            result.GetDisplayString()));
                                }
                            }
                        }
                    }
                },
                    SymbolKind.NamedType);
            });
        }
Exemplo n.º 3
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

            // Security analyzer - analyze and report diagnostics on generated code.
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                Compilation?compilation = compilationStartAnalysisContext.Compilation;
                WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation);

                if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemDataDataSet,
                        out INamedTypeSymbol? dataSetTypeSymbol) ||
                    !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemDataDataTable,
                        out INamedTypeSymbol? dataTableTypeSymbol))
                {
                    return;
                }

                INamedTypeSymbol?serializableAttributeTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemSerializableAttribute);

                INamedTypeSymbol?generatedCodeAttributeTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemCodeDomCompilerGeneratedCodeAttribute);

                // For completeness, could also consider CollectionDataContractAttribute
                INamedTypeSymbol?dataContractAttributeTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemRuntimeSerializationDataContractAttribute);
                INamedTypeSymbol?dataMemberAttributeTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemRuntimeSerializationDataMemberAttribute);
                INamedTypeSymbol?ignoreDataMemberTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemRuntimeSerializationIgnoreDataMemberAttribute);
                INamedTypeSymbol?knownTypeAttributeTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemRuntimeSerializationKnownTypeAttribute);

                XmlSerializationAttributeTypes xmlSerializationAttributeTypes = new XmlSerializationAttributeTypes(
                    wellKnownTypeProvider);
                if (serializableAttributeTypeSymbol == null &&
                    (dataContractAttributeTypeSymbol == null || dataMemberAttributeTypeSymbol == null) &&
                    ignoreDataMemberTypeSymbol == null &&
                    knownTypeAttributeTypeSymbol == null &&
                    !xmlSerializationAttributeTypes.Any)
                {
                    return;
                }

                INamedTypeSymbol?designerCategoryAttributeTypeSymbol =
                    wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemComponentModelDesignerCategoryAttribute);
                INamedTypeSymbol?typedTableBaseTypeSymbol =
                    wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemDataTypedTableBase1);

                InsecureDeserializationTypeDecider decider = InsecureDeserializationTypeDecider.GetOrCreate(compilation);

                ConcurrentDictionary <INamedTypeSymbol, bool> visitedTypes =
                    new ConcurrentDictionary <INamedTypeSymbol, bool>();

                compilationStartAnalysisContext.RegisterSymbolAction(
                    (SymbolAnalysisContext symbolAnalysisContext) =>
                {
                    INamedTypeSymbol namedTypeSymbol = (INamedTypeSymbol)symbolAnalysisContext.Symbol;
                    bool hasSerializableAttribute    = namedTypeSymbol.HasAttribute(serializableAttributeTypeSymbol);

                    bool hasDataContractAttribute        = namedTypeSymbol.HasAttribute(dataContractAttributeTypeSymbol);
                    bool hasKnownTypeAttribute           = namedTypeSymbol.HasAttribute(knownTypeAttributeTypeSymbol);
                    bool hasAnyIgnoreDataMemberAttribute =
                        namedTypeSymbol.GetMembers().Any(m => m.HasAttribute(ignoreDataMemberTypeSymbol));
                    bool hasAnyXmlSerializationAttributes =
                        xmlSerializationAttributeTypes.HasAnyAttribute(namedTypeSymbol) ||
                        namedTypeSymbol.GetMembers().Any(m => xmlSerializationAttributeTypes.HasAnyAttribute(m));
                    if (!hasSerializableAttribute &&
                        !hasDataContractAttribute &&
                        !hasKnownTypeAttribute &&
                        !hasAnyIgnoreDataMemberAttribute &&
                        !hasAnyXmlSerializationAttributes)
                    {
                        // Don't have any attributes suggesting this class is serialized.
                        return;
                    }

                    bool isProbablyAutogeneratedForGuiApp =
                        namedTypeSymbol.HasAttribute(designerCategoryAttributeTypeSymbol) ||
                        (namedTypeSymbol.BaseType != null &&
                         namedTypeSymbol.BaseType.IsGenericType &&
                         namedTypeSymbol.BaseType.ConstructedFrom.Equals(typedTableBaseTypeSymbol));

                    ObjectGraphOptions options = new ObjectGraphOptions(
                        recurse: false,
                        binarySerialization: hasSerializableAttribute,
                        dataContractSerialization:
                        hasDataContractAttribute ||
                        hasAnyIgnoreDataMemberAttribute ||
                        hasKnownTypeAttribute,
                        xmlSerialization: hasAnyXmlSerializationAttributes);

                    if (decider.IsObjectGraphInsecure(
                            namedTypeSymbol,
                            options,
                            out ImmutableArray <InsecureObjectGraphResult> results))
                    {
                        DiagnosticDescriptor diagnosticToReport;
                        if (hasSerializableAttribute)
                        {
                            diagnosticToReport =
                                isProbablyAutogeneratedForGuiApp
                                            ? RceAutogeneratedSerializableContainsDangerousType
                                            : RceSerializableContainsDangerousType;
                        }
                        else
                        {
                            diagnosticToReport = SerializableContainsDangerousType;
                        }

                        foreach (InsecureObjectGraphResult result in results)
                        {
                            symbolAnalysisContext.ReportDiagnostic(
                                Diagnostic.Create(
                                    diagnosticToReport,
                                    result.GetLocation(),
                                    result.InsecureType.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
                                    result.GetDisplayString()));
                        }
                    }
                },
                    SymbolKind.NamedType);
            });
        }
        public sealed override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

            // Security analyzer - analyze and report diagnostics on generated code.
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                Compilation?compilation = compilationStartAnalysisContext.Compilation;
                WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation);

                if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemDataDataSet,
                        out INamedTypeSymbol? dataSetTypeSymbol) ||
                    !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemDataDataTable,
                        out INamedTypeSymbol? dataTableTypeSymbol))
                {
                    return;
                }

                INamedTypeSymbol?serializableAttributeTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemSerializableAttribute);
                INamedTypeSymbol?nonSerializedAttributeTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemSerializableAttribute);
                INamedTypeSymbol?binaryFormatterTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemRuntimeSerializationFormattersBinaryBinaryFormatter);
                INamedTypeSymbol?netDataContractSerializerTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemRuntimeSerializationNetDataContractSerializer);
                INamedTypeSymbol?objectStateFormatterTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemWebUIObjectStateFormatter);
                INamedTypeSymbol?soapFormatterTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(
                    WellKnownTypeNames.SystemRuntimeSerializationFormattersSoapSoapFormatter);

                if (serializableAttributeTypeSymbol == null ||
                    (binaryFormatterTypeSymbol == null &&
                     netDataContractSerializerTypeSymbol == null &&
                     objectStateFormatterTypeSymbol == null &&
                     soapFormatterTypeSymbol == null))
                {
                    return;
                }

                InsecureDeserializationTypeDecider decider = InsecureDeserializationTypeDecider.GetOrCreate(compilation);

                compilationStartAnalysisContext.RegisterOperationAction(
                    (OperationAnalysisContext operationAnalysisContext) =>
                {
                    IInvocationOperation invocationOperation =
                        (IInvocationOperation)operationAnalysisContext.Operation;
                    string methodName = invocationOperation.TargetMethod.MetadataName;
                    if (!(((invocationOperation.Instance?.Type?.DerivesFrom(binaryFormatterTypeSymbol) == true &&
                            SecurityHelpers.BinaryFormatterDeserializationMethods.Contains(methodName)) ||
                           (invocationOperation.Instance?.Type?.DerivesFrom(netDataContractSerializerTypeSymbol) == true &&
                            SecurityHelpers.NetDataContractSerializerDeserializationMethods.Contains(methodName)) ||
                           (invocationOperation.Instance?.Type?.DerivesFrom(objectStateFormatterTypeSymbol) == true &&
                            SecurityHelpers.ObjectStateFormatterDeserializationMethods.Contains(methodName)) ||
                           (invocationOperation.Instance?.Type?.DerivesFrom(soapFormatterTypeSymbol) == true &&
                            SecurityHelpers.SoapFormatterDeserializationMethods.Contains(methodName))) &&
                          invocationOperation.Parent?.Kind == OperationKind.Conversion &&
                          invocationOperation.Parent is IConversionOperation conversionOperation))
                    {
                        return;
                    }

                    ITypeSymbol deserializedType = conversionOperation.Type;

                    ObjectGraphOptions options;
                    if (invocationOperation.Instance?.Type?.DerivesFrom(netDataContractSerializerTypeSymbol) == true)
                    {
                        options = ObjectGraphOptions.DataContractOptions;
                    }
                    else
                    {
                        options = ObjectGraphOptions.BinarySerializationOptions;
                    }

                    if (decider.IsObjectGraphInsecure(
                            deserializedType,
                            options,
                            out ImmutableArray <InsecureObjectGraphResult> results))
                    {
                        foreach (InsecureObjectGraphResult result in results)
                        {
                            operationAnalysisContext.ReportDiagnostic(
                                Diagnostic.Create(
                                    ObjectGraphContainsDangerousTypeDescriptor,
                                    invocationOperation.Parent.Syntax.GetLocation(),
                                    result.InsecureType.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
                                    result.GetDisplayString(typedConstant => ToString(typedConstant))));
                        }
                    }
                },
                    OperationKind.Invocation);
            });
        }