Esempio n. 1
0
 public bool HasTaintArraySource(SinkKind sinkKind, Configuration config)
 {
     return(GetSourceInfos(sinkKind, config).Any(o => o.TaintConstantArray));
 }
Esempio n. 2
0
        public TaintConfiguration(WellKnownTypeProvider wellKnownTypeProvider, Configuration config)
        {
            WellKnownTypeProvider = wellKnownTypeProvider;
            using PooledDictionary <SinkKind, Lazy <TaintedDataSymbolMap <SourceInfo> > > sourceSymbolMapBuilder =
                      PooledDictionary <SinkKind, Lazy <TaintedDataSymbolMap <SourceInfo> > > .GetInstance();

            using PooledDictionary <SinkKind, Lazy <TaintedDataSymbolMap <SanitizerInfo> > > sanitizerSymbolMapBuilder =
                      PooledDictionary <SinkKind, Lazy <TaintedDataSymbolMap <SanitizerInfo> > > .GetInstance();

            using PooledDictionary <SinkKind, Lazy <TaintedDataSymbolMap <SinkInfo> > > sinkSymbolMapBuilder =
                      PooledDictionary <SinkKind, Lazy <TaintedDataSymbolMap <SinkInfo> > > .GetInstance();

            // For tainted data rules with the same set of sources, we'll reuse the same TaintedDataSymbolMap<SourceInfo> instance.
            // Same for sanitizers.
            using PooledDictionary <ImmutableHashSet <SourceInfo>, Lazy <TaintedDataSymbolMap <SourceInfo> > > sourcesToSymbolMap =
                      PooledDictionary <ImmutableHashSet <SourceInfo>, Lazy <TaintedDataSymbolMap <SourceInfo> > > .GetInstance();

            using PooledDictionary <ImmutableHashSet <SanitizerInfo>, Lazy <TaintedDataSymbolMap <SanitizerInfo> > > sanitizersToSymbolMap =
                      PooledDictionary <ImmutableHashSet <SanitizerInfo>, Lazy <TaintedDataSymbolMap <SanitizerInfo> > > .GetInstance();

            // Build a mapping of (sourceSet, sanitizerSet) -> (sinkKinds, sinkSet), so we'll reuse the same TaintedDataSymbolMap<SinkInfo> instance.
            using PooledDictionary <(ImmutableHashSet <SourceInfo> SourceInfos, ImmutableHashSet <SanitizerInfo> SanitizerInfos), (ImmutableHashSet <SinkKind> .Builder SinkKinds, ImmutableHashSet <SinkInfo> .Builder SinkInfos)> sourceSanitizersToSinks =
                      PooledDictionary <(ImmutableHashSet <SourceInfo> SourceInfos, ImmutableHashSet <SanitizerInfo> SanitizerInfos), (ImmutableHashSet <SinkKind> .Builder SinkKinds, ImmutableHashSet <SinkInfo> .Builder SinkInfos)> .GetInstance();

            // Using LazyThreadSafetyMode.ExecutionAndPublication to avoid instantiating multiple times.
            foreach (SinkKind sinkKind in Enum.GetValues(typeof(TaintType)).Cast <SinkKind>().Except(ConstAnalyzer.ConstantTaintTypes.Cast <SinkKind>()))
            {
                ImmutableHashSet <SourceInfo> sources = GetSourceInfos(sinkKind, config);
                if (!sourcesToSymbolMap.TryGetValue(sources, out Lazy <TaintedDataSymbolMap <SourceInfo> > lazySourceSymbolMap))
                {
                    lazySourceSymbolMap = new Lazy <TaintedDataSymbolMap <SourceInfo> >(
                        () => { return(new TaintedDataSymbolMap <SourceInfo>(WellKnownTypeProvider, sources)); },
                        LazyThreadSafetyMode.ExecutionAndPublication);
                    sourcesToSymbolMap.Add(sources, lazySourceSymbolMap);
                }

                sourceSymbolMapBuilder.Add(sinkKind, lazySourceSymbolMap);

                ImmutableHashSet <SanitizerInfo> sanitizers = GetSanitizerInfos(sinkKind, config);
                if (!sanitizersToSymbolMap.TryGetValue(sanitizers, out Lazy <TaintedDataSymbolMap <SanitizerInfo> > lazySanitizerSymbolMap))
                {
                    lazySanitizerSymbolMap = new Lazy <TaintedDataSymbolMap <SanitizerInfo> >(
                        () => { return(new TaintedDataSymbolMap <SanitizerInfo>(WellKnownTypeProvider, sanitizers)); },
                        LazyThreadSafetyMode.ExecutionAndPublication);
                    sanitizersToSymbolMap.Add(sanitizers, lazySanitizerSymbolMap);
                }

                sanitizerSymbolMapBuilder.Add(sinkKind, lazySanitizerSymbolMap);

                ImmutableHashSet <SinkInfo> sinks = GetSinkInfos(sinkKind, config);
                if (!sourceSanitizersToSinks.TryGetValue((sources, sanitizers), out (ImmutableHashSet <SinkKind> .Builder SinkKinds, ImmutableHashSet <SinkInfo> .Builder SinkInfos)sinksPair))
                {
                    sinksPair = (ImmutableHashSet.CreateBuilder <SinkKind>(), ImmutableHashSet.CreateBuilder <SinkInfo>());
                    sourceSanitizersToSinks.Add((sources, sanitizers), sinksPair);
                }

                sinksPair.SinkKinds.Add(sinkKind);
                sinksPair.SinkInfos.UnionWith(sinks);
            }

            foreach (KeyValuePair <(ImmutableHashSet <SourceInfo> SourceInfos, ImmutableHashSet <SanitizerInfo> SanitizerInfos), (ImmutableHashSet <SinkKind> .Builder SinkKinds, ImmutableHashSet <SinkInfo> .Builder SinkInfos)> kvp in sourceSanitizersToSinks)
            {
                ImmutableHashSet <SinkInfo>             sinks             = kvp.Value.SinkInfos.ToImmutable();
                Lazy <TaintedDataSymbolMap <SinkInfo> > lazySinkSymbolMap = new Lazy <TaintedDataSymbolMap <SinkInfo> >(
                    () => { return(new TaintedDataSymbolMap <SinkInfo>(WellKnownTypeProvider, sinks)); },
                    LazyThreadSafetyMode.ExecutionAndPublication);
                foreach (SinkKind sinkKind in kvp.Value.SinkKinds)
                {
                    sinkSymbolMapBuilder.Add(sinkKind, lazySinkSymbolMap);
                }
            }

            foreach (SinkKind sinkKind in ConstAnalyzer.ConstantTaintTypes)
            {
                ImmutableHashSet <SinkInfo> sinks = GetSinkInfos(sinkKind, config);

                Lazy <TaintedDataSymbolMap <SinkInfo> > lazySinkSymbolMap = new Lazy <TaintedDataSymbolMap <SinkInfo> >(
                    () => { return(new TaintedDataSymbolMap <SinkInfo>(WellKnownTypeProvider, sinks)); },
                    LazyThreadSafetyMode.ExecutionAndPublication);

                sinkSymbolMapBuilder.Add(sinkKind, lazySinkSymbolMap);
            }

            SourceSymbolMap    = sourceSymbolMapBuilder.ToImmutableDictionary();
            SanitizerSymbolMap = sanitizerSymbolMapBuilder.ToImmutableDictionary();
            SinkSymbolMap      = sinkSymbolMapBuilder.ToImmutableDictionary();
        }
Esempio n. 3
0
        private ImmutableHashSet <SourceInfo> GetSourceInfos(SinkKind sinkKind, Configuration config)
        {
            var typeToInfos = new Dictionary <string, AggregatedSource>();

            foreach (var entryPoint in config.TaintEntryPoints)
            {
                if (!typeToInfos.TryGetValue(entryPoint.Key, out var value))
                {
                    value = new AggregatedSource();
                    typeToInfos.Add(entryPoint.Key, value);
                }

                if (value.entryPoint != null)
                {
                    throw new ArgumentException($"Duplicate entrypoint for type '{entryPoint.Key}'");
                }

                value.entryPoint = entryPoint.Value;
            }

            foreach (var source in config.TaintSources)
            {
                if (source.TaintTypes != null && !source.TaintTypes.Contains((TaintType)sinkKind))
                {
                    continue;
                }

                if (!typeToInfos.TryGetValue(source.Type, out var value))
                {
                    value = new AggregatedSource();
                    typeToInfos.Add(source.Type, value);
                }

                if (value.source != null)
                {
                    throw new ArgumentException($"Duplicate taint source for type '{source.Type}'");
                }

                value.source = source;
            }

            foreach (var sanitizer in config.Sanitizers)
            {
                var methods = sanitizer.Methods.Where(x => x.InOut != null && x.InOut.Any(io => io.outArgumentName != TaintedTargetValue.Return));
                if (!methods.Any())
                {
                    continue;
                }

                if (!typeToInfos.TryGetValue(sanitizer.Type, out var value))
                {
                    value = new AggregatedSource();
                    typeToInfos.Add(sanitizer.Type, value);
                }

                if (value.sanitizer != null)
                {
                    throw new ArgumentException($"Duplicate sanitizer for type '{sanitizer.Type}'");
                }

                value.sanitizer = sanitizer;
            }

            foreach (var transfer in config.Transfers)
            {
                if (!typeToInfos.TryGetValue(transfer.Type, out var value))
                {
                    value = new AggregatedSource();
                    typeToInfos.Add(transfer.Type, value);
                }

                if (value.transfer != null)
                {
                    throw new ArgumentException($"Duplicate taint source for type '{transfer.Type}'");
                }

                value.transfer = transfer;
            }

            var sourceInfosBuilder = PooledHashSet <SourceInfo> .GetInstance();

            foreach (var type in typeToInfos)
            {
                bool?isIterface = null;

                if (type.Value.sanitizer?.IsInterface != null)
                {
                    if (isIterface.HasValue && isIterface != type.Value.sanitizer.IsInterface)
                    {
                        throw new ArgumentException($"Inconsistent 'IsInterface' for type '{type.Key}'");
                    }
                    else
                    {
                        isIterface = type.Value.sanitizer.IsInterface;
                    }
                }

                if (type.Value.source?.IsInterface != null)
                {
                    if (isIterface.HasValue && isIterface != type.Value.sanitizer.IsInterface)
                    {
                        throw new ArgumentException($"Inconsistent 'IsInterface' for type '{type.Key}'");
                    }
                    else
                    {
                        isIterface = type.Value.source.IsInterface;
                    }
                }

                if (type.Value.transfer?.IsInterface != null)
                {
                    if (isIterface.HasValue && isIterface != type.Value.transfer.IsInterface)
                    {
                        throw new ArgumentException($"Inconsistent 'IsInterface' for type '{type.Key}'");
                    }
                    else
                    {
                        isIterface = type.Value.sanitizer.IsInterface;
                    }
                }

                SourceInfo metadata;

                if (type.Value.source != null && type.Value.source.Methods == null && type.Value.source.Properties == null)
                {
                    metadata = new SourceInfo(
                        type.Key,
                        isInterface: isIterface ?? false,
                        taintedMethods:
                        ImmutableHashSet <(MethodMatcher, ImmutableHashSet <string>)> .Empty,
                        taintedMethodsNeedsPointsToAnalysis:
                        ImmutableHashSet <(MethodMatcher, ImmutableHashSet <(PointsToCheck, string)>)> .Empty,
                        taintedMethodsNeedsValueContentAnalysis:
                        ImmutableHashSet <(MethodMatcher, ImmutableHashSet <(ValueContentCheck, string)>)> .Empty,
                        transferMethods:
                        ImmutableHashSet <(MethodMatcher, ImmutableHashSet <(string, string)>)> .Empty,
                        allProperitesAreTainted: true,
                        allFieldsAreTainted: true
                        );
                }
                else
                {
                    metadata = new SourceInfo(
                        type.Key,
                        isInterface: isIterface ?? false,
                        taintedProperties: type.Value.source?.Properties?.ToImmutableHashSet(StringComparer.Ordinal)
                        ?? ImmutableHashSet <string> .Empty,
                        dependencyFullTypeNames:
                        type.Value.entryPoint?.Dependency?.ToImmutableArray(),
                        taintedArguments: type.Value.entryPoint != null ?
                        new ParameterMatcher[] {
                        (parameter, wellKnownTypeProvider) => {
                            if (!(parameter.ContainingSymbol is IMethodSymbol methodSymbol) || methodSymbol.IsPropertyAccessor())
                            {
                                return(false);
                            }

                            if (type.Value.entryPoint.Class != null)
                            {
                                if (!(methodSymbol.ContainingSymbol is INamedTypeSymbol typeSymbol))
                                {
                                    return(false);
                                }

                                var classCache = s_classIsControllerByCompilation.GetOrCreateValue(wellKnownTypeProvider.Compilation, (compilation) => new ConcurrentDictionary <INamedTypeSymbol, bool>());
                                if (!classCache.TryGetValue(typeSymbol, out bool isTaintEntryClass))
                                {
                                    isTaintEntryClass = false;

                                    bool IsTaintEntryClassBySuffix()
                                    {
                                        if (typeSymbol.Name.EndsWith(type.Value.entryPoint.Class.Suffix.Text, StringComparison.Ordinal))
                                        {
                                            return(true);
                                        }
                                        else if (type.Value.entryPoint.Class.Suffix.IncludeParent &&
                                                 typeSymbol.GetBaseTypes().Any(x => x.Name.EndsWith(type.Value.entryPoint.Class.Suffix.Text, StringComparison.Ordinal)))
                                        {
                                            return(true);
                                        }
                                        else
                                        {
                                            return(false);
                                        }
                                    }

                                    if (type.Value.entryPoint.Class.Accessibility != null &&
                                        type.Value.entryPoint.Class.Accessibility.All(a => a != typeSymbol.DeclaredAccessibility))
                                    {
                                        isTaintEntryClass = false;
                                    }
                                    else
                                    {
                                        if (type.Value.entryPoint.Class.Suffix != null &&
                                            type.Value.entryPoint.Class.Parent == null)
                                        {
                                            isTaintEntryClass = IsTaintEntryClassBySuffix();
                                        }
                                        else if (type.Value.entryPoint.Class.Parent != null)
                                        {
                                            var parentType = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(type.Value.entryPoint.Class.Parent);
                                            if ((parentType.TypeKind == TypeKind.Interface && typeSymbol.AllInterfaces.Any(x => x == parentType)) ||
                                                typeSymbol.GetBaseTypesAndThis().Any(x => x == parentType))
                                            {
                                                isTaintEntryClass = type.Value.entryPoint.Class.Suffix != null ? IsTaintEntryClassBySuffix() : true;
                                            }
                                        }

                                        if (type.Value.entryPoint.Class.Attributes?.Exclude != null &&
                                            type.Value.entryPoint.Class.Attributes.Exclude.Any(x => typeSymbol.HasDerivedTypeAttribute(wellKnownTypeProvider.GetOrCreateTypeByMetadataName(x.Type))))
                                        {
                                            isTaintEntryClass = false;
                                        }
                                        else if (type.Value.entryPoint.Class.Attributes?.Include != null &&
                                                 type.Value.entryPoint.Class.Attributes.Include.Any(x => typeSymbol.HasDerivedTypeAttribute(wellKnownTypeProvider.GetOrCreateTypeByMetadataName(x.Type))))
                                        {
                                            isTaintEntryClass = true;
                                        }
                                    }

                                    classCache.TryAdd(typeSymbol, isTaintEntryClass);
                                }

                                if (!isTaintEntryClass)
                                {
                                    return(false);
                                }
                            }

                            if (type.Value.entryPoint.Method != null)
                            {
                                if (type.Value.entryPoint.Method.Static.HasValue && type.Value.entryPoint.Method.Static != methodSymbol.IsStatic)
                                {
                                    return(false);
                                }

                                if (type.Value.entryPoint.Method.Name != null)
                                {
                                    if (type.Value.entryPoint.Method.NameRegex == null)
                                    {
                                        return(type.Value.entryPoint.Method.Name == methodSymbol.Name);
                                    }

                                    if (!type.Value.entryPoint.Method.NameRegex.IsMatch(methodSymbol.Name))
                                    {
                                        return(false);
                                    }
                                }

                                if (type.Value.entryPoint.Method.IncludeConstructor.HasValue && type.Value.entryPoint.Method.IncludeConstructor != methodSymbol.IsConstructor())
                                {
                                    return(false);
                                }

                                if (type.Value.entryPoint.Method.Accessibility.All(a => a != methodSymbol.DeclaredAccessibility))
                                {
                                    return(false);
                                }

                                if (type.Value.entryPoint.Method.Attributes?.Exclude != null &&
                                    type.Value.entryPoint.Method.Attributes.Exclude.Any(x => methodSymbol.HasDerivedMethodAttribute(wellKnownTypeProvider.GetOrCreateTypeByMetadataName(x.Type))))
                                {
                                    return(false);
                                }
                            }

                            if (type.Value.entryPoint.Parameter?.Attributes?.Exclude != null &&
                                type.Value.entryPoint.Parameter.Attributes.Exclude.Any(x => parameter.HasAttribute(wellKnownTypeProvider.GetOrCreateTypeByMetadataName(x.Type))))
                            {
                                return(false);
                            }

                            return(true);
                        }
                    }.ToImmutableHashSet() : ImmutableHashSet <ParameterMatcher> .Empty,