protected override TaintedDataAbstractValue GetDefaultValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity) { if (this.DataFlowAnalysisContext.SourceInfos.IsSourceParameter(parameter, WellKnownTypeProvider)) { // Location of the parameter, so we can track where the tainted data appears in code. // The parameter itself may not have any DeclaringSyntaxReferences, e.g. 'value' inside property setters. SyntaxNode parameterSyntaxNode; if (!parameter.DeclaringSyntaxReferences.IsEmpty) { parameterSyntaxNode = parameter.DeclaringSyntaxReferences[0].GetSyntax(); } else if (!parameter.ContainingSymbol.DeclaringSyntaxReferences.IsEmpty) { parameterSyntaxNode = parameter.ContainingSymbol.DeclaringSyntaxReferences[0].GetSyntax(); } else { // Unless there are others, the only case we have for parameters being tainted data sources is inside // ASP.NET Core MVC controller action methods (see WebInputSources.cs), so those parameters should // always be declared somewhere. Debug.Fail("Can we have a tainted data parameter with no syntax references?"); return(ValueDomain.UnknownOrMayBeValue); } return(TaintedDataAbstractValue.CreateTainted(parameter, parameterSyntaxNode, this.OwningSymbol)); } return(ValueDomain.UnknownOrMayBeValue); }
public override TaintedDataAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, IOperation visitedInstance, ImmutableArray <IArgumentOperation> visitedArguments, bool invokedAsDelegate, IOperation originalOperation, TaintedDataAbstractValue defaultValue) { // Always invoke base visit. TaintedDataAbstractValue baseVisit = base.VisitInvocation_NonLambdaOrDelegateOrLocalFunction( method, visitedInstance, visitedArguments, invokedAsDelegate, originalOperation, defaultValue); IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(visitedArguments); if (taintedArguments.Any()) { ProcessTaintedDataEnteringInvocationOrCreation(method, taintedArguments, originalOperation); } if (this.IsSanitizingMethod(method)) { return(TaintedDataAbstractValue.NotTainted); } else if (this.DataFlowAnalysisContext.SourceInfos.IsSourceMethod(method)) { return(TaintedDataAbstractValue.CreateTainted(method, originalOperation.Syntax, this.OwningSymbol)); } return(baseVisit); }
protected override TaintedDataAbstractValue ComputeAnalysisValueForReferenceOperation(IOperation operation, TaintedDataAbstractValue defaultValue) { // If the property/field reference itself is a tainted data source if (operation is IPropertyReferenceOperation propertyReferenceOperation && this.DataFlowAnalysisContext.SourceInfos.IsSourceProperty(propertyReferenceOperation.Property)) { return(TaintedDataAbstractValue.CreateTainted(propertyReferenceOperation.Member, propertyReferenceOperation.Syntax, this.OwningSymbol)); }
protected override TaintedDataAbstractValue GetDefaultValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity) { if (this.DataFlowAnalysisContext.SourceInfos.IsSourceParameter(parameter, WellKnownTypeProvider)) { return(TaintedDataAbstractValue.CreateTainted(parameter, parameter.DeclaringSyntaxReferences[0].GetSyntax(), this.OwningSymbol)); } return(ValueDomain.UnknownOrMayBeValue); }
protected override TaintedDataAbstractValue ComputeAnalysisValueForReferenceOperation(IOperation operation, TaintedDataAbstractValue defaultValue) { // If the property reference itself is a tainted data source if (operation is IPropertyReferenceOperation propertyReferenceOperation && this.DataFlowAnalysisContext.SourceInfos.IsSourceProperty(propertyReferenceOperation.Property)) { return(TaintedDataAbstractValue.CreateTainted(propertyReferenceOperation.Member, propertyReferenceOperation.Syntax, this.OwningSymbol)); } if (AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity analysisEntity)) { return(this.CurrentAnalysisData.TryGetValue(analysisEntity, out TaintedDataAbstractValue value) ? value : defaultValue); } return(defaultValue); }
// So we can treat the array as tainted when it's passed to other object constructors. // See HttpRequest_Form_Array_List_Diagnostic and HttpRequest_Form_List_Diagnostic tests. public override TaintedDataAbstractValue VisitArrayInitializer(IArrayInitializerOperation operation, object argument) { HashSet <SymbolAccess> sourceOrigins = null; TaintedDataAbstractValue baseAbstractValue = base.VisitArrayInitializer(operation, argument); if (baseAbstractValue.Kind == TaintedDataAbstractValueKind.Tainted) { sourceOrigins = new HashSet <SymbolAccess>(baseAbstractValue.SourceOrigins); } IEnumerable <TaintedDataAbstractValue> taintedAbstractValues = operation.ElementValues .Select <IOperation, TaintedDataAbstractValue>(e => this.GetCachedAbstractValue(e)) .Where(v => v.Kind == TaintedDataAbstractValueKind.Tainted); if (baseAbstractValue.Kind == TaintedDataAbstractValueKind.Tainted) { taintedAbstractValues = taintedAbstractValues.Concat(baseAbstractValue); } TaintedDataAbstractValue result = null; if (taintedAbstractValues.Any()) { result = TaintedDataAbstractValue.MergeTainted(taintedAbstractValues); } IArrayCreationOperation arrayCreationOperation = operation.GetAncestor <IArrayCreationOperation>(OperationKind.ArrayCreation); if (arrayCreationOperation?.Type is IArrayTypeSymbol arrayTypeSymbol && this.DataFlowAnalysisContext.SourceInfos.IsSourceConstantArrayOfType(arrayTypeSymbol) && operation.ElementValues.All(s => GetValueContentAbstractValue(s).IsLiteralState)) { TaintedDataAbstractValue taintedDataAbstractValue = TaintedDataAbstractValue.CreateTainted(arrayTypeSymbol, arrayCreationOperation.Syntax, this.OwningSymbol); result = result == null ? taintedDataAbstractValue : TaintedDataAbstractValue.MergeTainted(result, taintedDataAbstractValue); } if (result != null) { return(result); } else { return(baseAbstractValue); } }
public override TaintedDataAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, IOperation visitedInstance, ImmutableArray <IArgumentOperation> visitedArguments, bool invokedAsDelegate, IOperation originalOperation, TaintedDataAbstractValue defaultValue) { // Always invoke base visit. TaintedDataAbstractValue result = base.VisitInvocation_NonLambdaOrDelegateOrLocalFunction( method, visitedInstance, visitedArguments, invokedAsDelegate, originalOperation, defaultValue); IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(visitedArguments); if (taintedArguments.Any()) { ProcessTaintedDataEnteringInvocationOrCreation(method, taintedArguments, originalOperation); } PooledHashSet <string> taintedTargets = null; PooledHashSet <(string, string)> taintedParameterPairs = null; try { if (this.IsSanitizingMethod(method)) { result = TaintedDataAbstractValue.NotTainted; } else if (visitedInstance != null && this.IsSanitizingInstanceMethod(method)) { result = TaintedDataAbstractValue.NotTainted; SetTaintedForEntity(visitedInstance, result); } else if (this.DataFlowAnalysisContext.SourceInfos.IsSourceMethod( method, visitedArguments, new Lazy <PointsToAnalysisResult>(() => DataFlowAnalysisContext.PointsToAnalysisResultOpt), new Lazy <ValueContentAnalysisResult>(() => DataFlowAnalysisContext.ValueContentAnalysisResultOpt), out taintedTargets)) { foreach (string taintedTarget in taintedTargets) { if (taintedTarget != TaintedTargetValue.Return) { IArgumentOperation argumentOperation = visitedArguments.FirstOrDefault(o => o.Parameter.Name == taintedTarget); if (argumentOperation != null) { this.CacheAbstractValue(argumentOperation, TaintedDataAbstractValue.CreateTainted(argumentOperation.Parameter, argumentOperation.Syntax, method)); } else { Debug.Fail("Are the tainted data sources misconfigured?"); } } else { result = TaintedDataAbstractValue.CreateTainted(method, originalOperation.Syntax, this.OwningSymbol); } } } if (this.DataFlowAnalysisContext.SourceInfos.IsSourceTransferMethod( method, visitedArguments, visitedArguments .Where(s => this.GetCachedAbstractValue(s).Kind == TaintedDataAbstractValueKind.Tainted) .Select(s => s.Parameter.Name) .ToImmutableArray(), out taintedParameterPairs)) { foreach ((string ifTaintedParameter, string thenTaintedTarget) in taintedParameterPairs) { IArgumentOperation thenTaintedTargetOperation = visitedArguments.FirstOrDefault(o => o.Parameter.Name == thenTaintedTarget); if (thenTaintedTargetOperation != null) { SetTaintedForEntity( thenTaintedTargetOperation, this.GetCachedAbstractValue( visitedArguments.FirstOrDefault(o => o.Parameter.Name == ifTaintedParameter))); } else { Debug.Fail("Are the tainted data sources misconfigured?"); } } } } finally { taintedTargets?.Free(); taintedParameterPairs?.Free(); } return(result); }
public override TaintedDataAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, IOperation?visitedInstance, ImmutableArray <IArgumentOperation> visitedArguments, bool invokedAsDelegate, IOperation originalOperation, TaintedDataAbstractValue defaultValue) { // Always invoke base visit. TaintedDataAbstractValue result = base.VisitInvocation_NonLambdaOrDelegateOrLocalFunction( method, visitedInstance, visitedArguments, invokedAsDelegate, originalOperation, defaultValue); IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(visitedArguments); if (taintedArguments.Any()) { ProcessTaintedDataEnteringInvocationOrCreation(method, taintedArguments, originalOperation); } PooledHashSet <string>? taintedTargets = null; PooledHashSet <(string, string)>?taintedParameterPairs = null; PooledHashSet <(string, string)>?sanitizedParameterPairs = null; PooledHashSet <string>? taintedParameterNamesCached = null; try { IEnumerable <string> GetTaintedParameterNames() { IEnumerable <string> taintedParameterNames = visitedArguments .Where(s => this.GetCachedAbstractValue(s).Kind == TaintedDataAbstractValueKind.Tainted) .Select(s => s.Parameter.Name); if (visitedInstance != null && this.GetCachedAbstractValue(visitedInstance).Kind == TaintedDataAbstractValueKind.Tainted) { taintedParameterNames = taintedParameterNames.Concat(TaintedTargetValue.This); } return(taintedParameterNames); } taintedParameterNamesCached = PooledHashSet <string> .GetInstance(); taintedParameterNamesCached.UnionWith(GetTaintedParameterNames()); if (this.DataFlowAnalysisContext.SourceInfos.IsSourceMethod( method, visitedArguments, new Lazy <PointsToAnalysisResult?>(() => DataFlowAnalysisContext.PointsToAnalysisResult), new Lazy <(PointsToAnalysisResult?, ValueContentAnalysisResult?)>(() => (DataFlowAnalysisContext.PointsToAnalysisResult, DataFlowAnalysisContext.ValueContentAnalysisResult)), out taintedTargets)) { bool rebuildTaintedParameterNames = false; foreach (string taintedTarget in taintedTargets) { if (taintedTarget != TaintedTargetValue.Return) { IArgumentOperation argumentOperation = visitedArguments.FirstOrDefault(o => o.Parameter.Name == taintedTarget); if (argumentOperation != null) { rebuildTaintedParameterNames = true; this.CacheAbstractValue(argumentOperation, TaintedDataAbstractValue.CreateTainted(argumentOperation.Parameter, argumentOperation.Syntax, method)); } else { Debug.Fail("Are the tainted data sources misconfigured?"); } } else { result = TaintedDataAbstractValue.CreateTainted(method, originalOperation.Syntax, this.OwningSymbol); } } if (rebuildTaintedParameterNames) { taintedParameterNamesCached.Clear(); taintedParameterNamesCached.UnionWith(GetTaintedParameterNames()); } } if (this.DataFlowAnalysisContext.SourceInfos.IsSourceTransferMethod( method, visitedArguments, taintedParameterNamesCached, out taintedParameterPairs)) { foreach ((string ifTaintedParameter, string thenTaintedTarget) in taintedParameterPairs) { IOperation thenTaintedTargetOperation = visitedInstance != null && thenTaintedTarget == TaintedTargetValue.This ? visitedInstance : visitedArguments.FirstOrDefault(o => o.Parameter.Name == thenTaintedTarget); if (thenTaintedTargetOperation != null) { SetTaintedForEntity( thenTaintedTargetOperation, this.GetCachedAbstractValue( visitedInstance != null && ifTaintedParameter == TaintedTargetValue.This ? visitedInstance : visitedArguments.FirstOrDefault(o => o.Parameter.Name == ifTaintedParameter))); } else { Debug.Fail("Are the tainted data sources misconfigured?"); } } } if (visitedInstance != null && this.IsSanitizingInstanceMethod(method)) { SetTaintedForEntity(visitedInstance, TaintedDataAbstractValue.NotTainted); } if (this.IsSanitizingMethod( method, visitedArguments, taintedParameterNamesCached, out sanitizedParameterPairs)) { if (sanitizedParameterPairs.Count == 0) { // it was either sanitizing constructor or // the short form or registering sanitizer method by just the name result = TaintedDataAbstractValue.NotTainted; } else { foreach ((string ifTaintedParameter, string thenSanitizedTarget) in sanitizedParameterPairs) { if (thenSanitizedTarget == TaintedTargetValue.Return) { result = TaintedDataAbstractValue.NotTainted; continue; } IArgumentOperation thenSanitizedTargetOperation = visitedArguments.FirstOrDefault(o => o.Parameter.Name == thenSanitizedTarget); if (thenSanitizedTargetOperation != null) { SetTaintedForEntity(thenSanitizedTargetOperation, TaintedDataAbstractValue.NotTainted); } else { Debug.Fail("Are the tainted data sanitizers misconfigured?"); } } } } } finally { taintedTargets?.Dispose(); taintedParameterPairs?.Dispose(); sanitizedParameterPairs?.Dispose(); taintedParameterNamesCached?.Dispose(); } return(result); }
public override TaintedDataAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, IOperation visitedInstance, ImmutableArray <IArgumentOperation> visitedArguments, bool invokedAsDelegate, IOperation originalOperation, TaintedDataAbstractValue defaultValue) { // Always invoke base visit. TaintedDataAbstractValue baseVisit = base.VisitInvocation_NonLambdaOrDelegateOrLocalFunction( method, visitedInstance, visitedArguments, invokedAsDelegate, originalOperation, defaultValue); IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(visitedArguments); if (taintedArguments.Any()) { ProcessTaintedDataEnteringInvocationOrCreation(method, taintedArguments, originalOperation); } PooledHashSet <IsInvocationTaintedWithPointsToAnalysis> evaluateWithPointsToAnalysis = null; PooledHashSet <IsInvocationTaintedWithValueContentAnalysis> evaluateWithValueContentAnalysis = null; try { if (this.IsSanitizingMethod(method)) { return(TaintedDataAbstractValue.NotTainted); } else if (visitedInstance != null && this.IsSanitizingInstanceMethod(method)) { if (AnalysisEntityFactory.TryCreate(visitedInstance, out AnalysisEntity analysisEntity)) { this.CurrentAnalysisData.SetAbstractValue(analysisEntity, TaintedDataAbstractValue.NotTainted); } return(TaintedDataAbstractValue.NotTainted); } else if (this.DataFlowAnalysisContext.SourceInfos.IsSourceMethod( method, out evaluateWithPointsToAnalysis, out evaluateWithValueContentAnalysis)) { ImmutableArray <IArgumentOperation> argumentOperation = (originalOperation as IInvocationOperation).Arguments; IEnumerable <PointsToAbstractValue> pointsToAnalysisResult = argumentOperation.Select(o => GetPointsToAbstractValue(o.Value)); IEnumerable <ValueContentAbstractValue> valueContentAnalysisResult = argumentOperation.Select(o => GetValueContentAbstractValue(o.Value)); if ((evaluateWithPointsToAnalysis != null && evaluateWithPointsToAnalysis.Any(o => o(pointsToAnalysisResult))) || (evaluateWithValueContentAnalysis != null && evaluateWithValueContentAnalysis.Any(o => o(pointsToAnalysisResult, valueContentAnalysisResult)))) { return(TaintedDataAbstractValue.CreateTainted(method, originalOperation.Syntax, this.OwningSymbol)); } return(TaintedDataAbstractValue.NotTainted); } } finally { if (evaluateWithPointsToAnalysis != null) { evaluateWithPointsToAnalysis.Free(); } if (evaluateWithValueContentAnalysis != null) { evaluateWithValueContentAnalysis.Free(); } } return(baseVisit); }