private VariableState VisitMethodInvocation(InvocationExpressionSyntax node, ExecutionState state) { VariableState memberVariableState = null; if (node.Expression is MemberAccessExpressionSyntax memberAccessExpression) { if (memberAccessExpression.Expression != null) { memberVariableState = VisitExpression(memberAccessExpression.Expression, state); } else { var with = memberAccessExpression.AncestorsAndSelf().OfType <WithBlockSyntax>().First(); memberVariableState = VisitExpression(with.WithStatement.Expression, state); } } return(VisitInvocationAndCreation(node, node.ArgumentList, state, memberVariableState)); }
public void AddOrUpdateValue(string identifier, VariableState value) { if (VariableStates.ContainsKey(identifier)) //Override existing value { VariableStates[identifier].Replace(value); #if DEBUG Logger.Log($"Updating state for {identifier} ({value})"); #endif } else { //Unexpected state #if DEBUG Logger.Log($"Adding state for {identifier} ({value})"); #endif Variables.Add(identifier, value); } }
private VariableState VisitCollectionRangeVariable(CollectionRangeVariableSyntax collectionRangeVariableSyntax, ExecutionState state) { var expressionState = VisitExpression(collectionRangeVariableSyntax.Expression, state); var fromSymbol = SyntaxNodeHelper.GetSymbol(collectionRangeVariableSyntax.Expression, state.AnalysisContext.SemanticModel); if (fromSymbol != null) { switch (fromSymbol) { case IPropertySymbol propertyFromSymbol when propertyFromSymbol.Type.IsTaintType(ProjectConfiguration.Behavior): case IFieldSymbol fieldFromSymbol when fieldFromSymbol.Type.IsTaintType(ProjectConfiguration.Behavior): expressionState = new VariableState(collectionRangeVariableSyntax, VariableTaint.Tainted); break; } } state.AddNewValue(ResolveIdentifier(collectionRangeVariableSyntax.Identifier.Identifier), expressionState); return(expressionState); }
private VariableState VisitObjectCreation(ObjectCreationExpressionSyntax node, ExecutionState state) { VariableState finalState = VisitInvocationAndCreation(node, node.ArgumentList, state); foreach (SyntaxNode child in node.DescendantNodes()) { if (child is NamedFieldInitializerSyntax namedFieldInitializerSyntax) { VisitNamedFieldInitializer(namedFieldInitializerSyntax, state, finalState); } else { #if DEBUG Logger.Log(child.GetText().ToString().Trim() + " -> " + finalState); #endif } } return(finalState); }
private VariableState VisitObjectCreation(ObjectCreationExpressionSyntax node, ExecutionState state) { VariableState finalState = VisitInvocationAndCreation(node, node.ArgumentList, state); foreach (SyntaxNode child in node.DescendantNodes()) { if (child is AssignmentExpressionSyntax assignmentExpressionSyntax) { var assignmentState = VisitAssignment(assignmentExpressionSyntax, state); MergeVariableState(assignmentExpressionSyntax.Left, assignmentState, state, finalState); } else { #if DEBUG Logger.Log(child.GetText().ToString().Trim() + " -> " + finalState); #endif } } return(finalState); }
private VariableState VisitElementAccess(ElementAccessExpressionSyntax elementAccess, BracketedArgumentListSyntax argumentList, ExecutionState state) { var finalState = new VariableState(elementAccess, VariableTaint.Unset); foreach (var argument in argumentList.Arguments) { finalState.MergeTaint(VisitExpression(argument.Expression, state).Taint); } finalState.MergeTaint(VisitExpression(elementAccess.Expression, state).Taint); var taintSourceState = CheckIfTaintSource(elementAccess, state); if (taintSourceState != null) { finalState.MergeTaint(taintSourceState.Taint); } return(finalState); }
public static void Merge(Queue <KeyValuePair <VariableState, VariableState> > queue, Dictionary <VariableState, VariableState> otherToSelf) { while (queue.Any()) { var correspondingVariables = queue.Dequeue(); var otherVariable = correspondingVariables.Key; var selfVariable = correspondingVariables.Value; selfVariable.MergeTaint(otherVariable.Taint, otherVariable.Value); foreach (var otherProperty in otherVariable.PropertyStates) { selfVariable.PropertyStates.TryGetValue(otherProperty.Key, out var selfProperty); otherToSelf.TryGetValue(otherProperty.Value, out var correspondingSelfProperty); if (selfProperty == null) { if (correspondingSelfProperty == null) { correspondingSelfProperty = new VariableState(otherProperty.Value.Node, otherProperty.Value.Taint, otherProperty.Value.Value); otherToSelf.Add(otherProperty.Value, correspondingSelfProperty); } selfVariable.Properties.Add(otherProperty.Key, correspondingSelfProperty); } else if (correspondingSelfProperty != null) { continue; } queue.Enqueue(new KeyValuePair <VariableState, VariableState>( otherProperty.Value, selfVariable.PropertyStates[otherProperty.Key])); } } }
/// <summary> /// Evaluate expression that contains a list of assignment. /// </summary> /// <param name="declaration"></param> /// <param name="state"></param> private VariableState VisitVariableDeclaration(VariableDeclaratorSyntax declaration, ExecutionState state) { var lastState = new VariableState(declaration, VariableTaint.Unknown); foreach (var variable in declaration.Names) { VariableState varState; if (declaration.Initializer != null) { varState = VisitExpression(declaration.Initializer.Value, state); var type = state.AnalysisContext.SemanticModel.GetTypeInfo(declaration.Initializer.Value); if (type.ConvertedType != null && (type.ConvertedType.IsType("System.String") || type.ConvertedType.IsValueType)) { var copy = new VariableState(varState.Node, varState.Taint, varState.Value); foreach (var property in varState.PropertyStates) { copy.AddProperty(property.Key, property.Value); } varState = copy; } } else if (declaration.AsClause is AsNewClauseSyntax asNewClauseSyntax) { varState = VisitExpression(asNewClauseSyntax.NewExpression, state); } else { varState = new VariableState(variable, VariableTaint.Constant); } state.AddNewValue(ResolveIdentifier(variable.Identifier), varState); lastState = varState; } return(lastState); }
private VariableState VisitInterpolatedString(InterpolatedStringExpressionSyntax interpolatedString, ExecutionState state) { var varState = new VariableState(interpolatedString, VariableTaint.Constant); foreach (var content in interpolatedString.Contents) { if (content is InterpolatedStringTextSyntax textString) { varState = varState.Merge(new VariableState(textString, VariableTaint.Constant)); } if (!(content is InterpolationSyntax interpolation)) { continue; } var expressionState = VisitExpression(interpolation.Expression, state); varState = varState.Merge(expressionState); } return(varState); }
private VariableState MergeVariableState(ExpressionSyntax expression, VariableState newVariableState, ExecutionState state, VariableState currentScope = null) { var variableStateToMerge = newVariableState ?? new VariableState(expression, VariableTaint.Unset); if (!(expression is MemberAccessExpressionSyntax memberAccessExpressionSyntax)) { var identifier = ""; if (expression is IdentifierNameSyntax identifierNameSyntax) { identifier = ResolveIdentifier(identifierNameSyntax.Identifier); } else if (expression is MeExpressionSyntax) { identifier = "this"; } if (currentScope != null) { currentScope.AddOrMergeProperty(identifier, variableStateToMerge); return(currentScope.PropertyStates[identifier]); } state.AddOrUpdateValue(identifier, variableStateToMerge); return(state.VariableStates[identifier]); } var variableState = MergeVariableState(memberAccessExpressionSyntax.Expression, null, state, currentScope); var stateIdentifier = ResolveIdentifier(memberAccessExpressionSyntax.Name.Identifier); //make sure this identifier exists variableState.AddOrMergeProperty(stateIdentifier, variableStateToMerge); return(variableState.PropertyStates[stateIdentifier]); }
public void MergeValue(string identifier, VariableState value) { if (VariableStates.ContainsKey(identifier)) //Override existing value { var state = VariableStates[identifier]; var newState = state.Merge(value); Variables.Remove(identifier); Variables.Add(identifier, newState); if (DebugMode) { Logger.Log($"Merging state for {identifier} ({newState})"); } } else { //Unexpected state if (DebugMode) { Logger.Log($"Merging state for {identifier} ({value}) .. /!\\ unexpected state"); } Variables.Add(identifier, value); } }
/// <summary> /// Evaluate expression that contains a list of assignment. /// </summary> /// <param name="declaration"></param> /// <param name="state"></param> private VariableState VisitVariableDeclaration(VariableDeclarationSyntax declaration, ExecutionState state) { var lastState = new VariableState(declaration, VariableTaint.Unknown); foreach (var variable in declaration.Variables) { var identifier = variable.Identifier; var initializer = variable.Initializer; if (initializer == null) { continue; } EqualsValueClauseSyntax equalsClause = initializer; VariableState varState = VisitExpression(equalsClause.Value, state); //varState.SetType(lastState.type); state.AddNewValue(ResolveIdentifier(identifier), varState); lastState = varState; } // return(lastState); }
private VariableState VisitExpression(ExpressionSyntax expression, ExecutionState state) { // TODO: Review other expression types that are unique to VB. // TODO: Write tests to cover all these. switch (expression) { case ParenthesizedExpressionSyntax parenthesizedExpressionSyntax: return(VisitExpression(parenthesizedExpressionSyntax.Expression, state)); case InvocationExpressionSyntax invocationExpressionSyntax: return(VisitMethodInvocation(invocationExpressionSyntax, state)); case ObjectCreationExpressionSyntax objectCreationExpressionSyntax: return(VisitObjectCreation(objectCreationExpressionSyntax, state)); case LiteralExpressionSyntax literalExpressionSyntax: return(new VariableState(literalExpressionSyntax, VariableTaint.Constant, literalExpressionSyntax.Token.Value)); case IdentifierNameSyntax identifierNameSyntax: return(VisitIdentifierName(identifierNameSyntax, state)); case BinaryExpressionSyntax binaryExpressionSyntax: return(VisitBinaryExpression(binaryExpressionSyntax, binaryExpressionSyntax.Left, binaryExpressionSyntax.Right, state)); case BinaryConditionalExpressionSyntax binaryConditionalExpressionSyntax: return(VisitBinaryExpression(binaryConditionalExpressionSyntax, binaryConditionalExpressionSyntax.FirstExpression, binaryConditionalExpressionSyntax.SecondExpression, state)); case MemberAccessExpressionSyntax memberAccessExpressionSyntax: return(VisitMemberAccessExpression(memberAccessExpressionSyntax, state)); case ArrayCreationExpressionSyntax arrayCreationExpressionSyntax: return(VisitArrayCreation(arrayCreationExpressionSyntax, arrayCreationExpressionSyntax.Initializer, state)); case CollectionInitializerSyntax collectionInitializerSyntax: return(VisitArrayCreation(collectionInitializerSyntax, collectionInitializerSyntax, state)); case TypeOfExpressionSyntax typeOfExpressionSyntax: return(new VariableState(typeOfExpressionSyntax, VariableTaint.Safe)); case GetTypeExpressionSyntax getTypeExpressionSyntax: return(new VariableState(getTypeExpressionSyntax, VariableTaint.Safe)); case TernaryConditionalExpressionSyntax ternaryConditionalExpressionSyntax: { VisitExpression(ternaryConditionalExpressionSyntax.Condition, state); var finalState = new VariableState(ternaryConditionalExpressionSyntax, VariableTaint.Unset); var whenTrueState = VisitExpression(ternaryConditionalExpressionSyntax.WhenTrue, state); finalState.MergeTaint(whenTrueState.Taint); var whenFalseState = VisitExpression(ternaryConditionalExpressionSyntax.WhenFalse, state); finalState.MergeTaint(whenFalseState.Taint); return(finalState); } case QueryExpressionSyntax queryExpressionSyntax: { var finalState = new VariableState(queryExpressionSyntax, VariableTaint.Unset); foreach (var clause in queryExpressionSyntax.Clauses) { finalState.MergeTaint(VisitNode(clause, state).Taint); } return(finalState); } case InterpolatedStringExpressionSyntax interpolatedStringExpressionSyntax: return(VisitInterpolatedString(interpolatedStringExpressionSyntax, state)); case DirectCastExpressionSyntax directCastExpressionSyntax: return(VisitExpression(directCastExpressionSyntax.Expression, state)); case CTypeExpressionSyntax cTypeExpressionSyntax: return(VisitExpression(cTypeExpressionSyntax.Expression, state)); case UnaryExpressionSyntax unaryExpressionSyntax: return(VisitExpression(unaryExpressionSyntax.Operand, state)); } #if DEBUG Logger.Log("Unsupported expression " + expression.GetType() + " (" + expression + ")"); #endif return(new VariableState(expression, VariableTaint.Unknown)); }
public void AddProperty(string identifier, VariableState secondState) { Properties.Add(identifier, secondState); }
public virtual void VisitArrowExpressionClause(CSharpSyntax.ArrowExpressionClauseSyntax node, ExecutionState state, VariableState statementState, Configuration projectConfiguration) { }
private VariableState VisitNamedFieldInitializer(NamedFieldInitializerSyntax node, ExecutionState state, VariableState currentScope) { var assignmentState = VisitAssignment(node, node.Name, node.Expression, state); return(MergeVariableState(node.Name, assignmentState, state, currentScope)); }
public virtual void VisitStatement(VBSyntax.StatementSyntax node, ExecutionState state, VariableState statementState, Configuration projectConfiguration) { }
private VariableState VisitExpression(ExpressionSyntax expression, ExecutionState state) { // TODO: Review other expression types that are unique to VB. // TODO: Write tests to cover all these. switch (expression) { case InvocationExpressionSyntax invocationExpressionSyntax: return(VisitMethodInvocation(invocationExpressionSyntax, state)); case ObjectCreationExpressionSyntax objectCreationExpressionSyntax: return(VisitObjectCreation(objectCreationExpressionSyntax, state)); case LiteralExpressionSyntax _: return(new VariableState(expression, VariableTaint.Constant)); case IdentifierNameSyntax identifierNameSyntax: return(VisitIdentifierName(identifierNameSyntax, state)); case BinaryExpressionSyntax binaryExpressionSyntax: return(VisitBinaryExpression(binaryExpressionSyntax, state)); case MemberAccessExpressionSyntax memberAccessExpressionSyntax: return(VisitExpression(memberAccessExpressionSyntax.Name, state)); case ArrayCreationExpressionSyntax arrayCreationExpressionSyntax: return(VisitArrayCreation(arrayCreationExpressionSyntax, arrayCreationExpressionSyntax.Initializer, state)); case CollectionInitializerSyntax collectionInitializerSyntax: return(VisitArrayCreation(collectionInitializerSyntax, collectionInitializerSyntax, state)); case TypeOfExpressionSyntax typeOfExpressionSyntax: return(new VariableState(typeOfExpressionSyntax, VariableTaint.Safe)); case GetTypeExpressionSyntax getTypeExpressionSyntax: return(new VariableState(getTypeExpressionSyntax, VariableTaint.Safe)); case TernaryConditionalExpressionSyntax ternaryConditionalExpressionSyntax: { VisitExpression(ternaryConditionalExpressionSyntax.Condition, state); var finalState = new VariableState(ternaryConditionalExpressionSyntax, VariableTaint.Safe); var whenTrueState = VisitExpression(ternaryConditionalExpressionSyntax.WhenTrue, state); finalState = finalState.Merge(whenTrueState); var whenFalseState = VisitExpression(ternaryConditionalExpressionSyntax.WhenFalse, state); finalState = finalState.Merge(whenFalseState); return(finalState); } case QueryExpressionSyntax queryExpressionSyntax: return(new VariableState(queryExpressionSyntax, VariableTaint.Unknown)); case DirectCastExpressionSyntax directCastExpressionSyntax: return(VisitExpression(directCastExpressionSyntax.Expression, state)); case CTypeExpressionSyntax cTypeExpressionSyntax: return(VisitExpression(cTypeExpressionSyntax.Expression, state)); } Logger.Log("Unsupported expression " + expression.GetType() + " (" + expression + ")"); return(new VariableState(expression, VariableTaint.Unknown)); }
private VariableState VisitStatements(SyntaxList <StatementSyntax> statements, ExecutionState state, VariableState lastState) { foreach (StatementSyntax statement in statements) { var statementState = VisitNode(statement, state); lastState = statementState; foreach (var ext in Extensions) { ext.VisitStatement(statement, state); } } return(lastState); }
private void CollectVariableStates(Dictionary <VariableState, VariableState> otherVariableStateToNew, VariableState other) { if (otherVariableStateToNew.ContainsKey(other)) { return; } otherVariableStateToNew.Add(other, new VariableState(other.Node, other.Taint, other.Value)); foreach (var otherVariablePair in other.PropertyStates) { CollectVariableStates(otherVariableStateToNew, otherVariablePair.Value); } }
private VariableState VisitExpression(ExpressionSyntax expression, ExecutionState state) { switch (expression) { case InvocationExpressionSyntax invocationExpressionSyntax: return(VisitMethodInvocation(invocationExpressionSyntax, state)); case ObjectCreationExpressionSyntax objectCreationExpressionSyntax: return(VisitObjectCreation(objectCreationExpressionSyntax, state)); case LiteralExpressionSyntax _: return(new VariableState(expression, VariableTaint.Constant)); case IdentifierNameSyntax identifierNameSyntax: return(VisitIdentifierName(identifierNameSyntax, state)); case BinaryExpressionSyntax binaryExpressionSyntax: { switch (binaryExpressionSyntax.Kind()) { case SyntaxKind.AsExpression: case SyntaxKind.IsExpression: return(VisitNode(binaryExpressionSyntax.Left, state)); } return(VisitBinaryExpression(binaryExpressionSyntax, state)); } case AssignmentExpressionSyntax assignmentExpressionSyntax: return(VisitAssignment(assignmentExpressionSyntax, state)); case MemberAccessExpressionSyntax memberAccessExpressionSyntax: return(VisitExpression(memberAccessExpressionSyntax.Name, state)); case ElementAccessExpressionSyntax elementAccessExpressionSyntax: return(VisitElementAccess(elementAccessExpressionSyntax, elementAccessExpressionSyntax.ArgumentList, state)); case ArrayCreationExpressionSyntax arrayCreationExpressionSyntax: return(VisitArrayCreation(arrayCreationExpressionSyntax, arrayCreationExpressionSyntax.Initializer, state)); case ImplicitArrayCreationExpressionSyntax implicitArrayCreationExpressionSyntax: return(VisitArrayCreation(implicitArrayCreationExpressionSyntax, implicitArrayCreationExpressionSyntax.Initializer, state)); case TypeOfExpressionSyntax typeOfExpressionSyntax: return(new VariableState(typeOfExpressionSyntax, VariableTaint.Safe)); case ConditionalExpressionSyntax conditionalExpressionSyntax: VisitExpression(conditionalExpressionSyntax.Condition, state); var finalState = new VariableState(conditionalExpressionSyntax, VariableTaint.Safe); var whenTrueState = VisitExpression(conditionalExpressionSyntax.WhenTrue, state); finalState = finalState.Merge(whenTrueState); var whenFalseState = VisitExpression(conditionalExpressionSyntax.WhenFalse, state); finalState = finalState.Merge(whenFalseState); return(finalState); case CheckedExpressionSyntax checkedExpressionSyntax: return(VisitExpression(checkedExpressionSyntax.Expression, state)); case QueryExpressionSyntax queryExpressionSyntax: return(new VariableState(queryExpressionSyntax, VariableTaint.Unknown)); case InterpolatedStringExpressionSyntax interpolatedStringExpressionSyntax: return(VisitInterpolatedString(interpolatedStringExpressionSyntax, state)); case CastExpressionSyntax castExpressionSyntax: return(VisitExpression(castExpressionSyntax.Expression, state)); case DefaultExpressionSyntax defaultExpressionSyntax: return(new VariableState(defaultExpressionSyntax, VariableTaint.Constant)); } Logger.Log("Unsupported expression " + expression.GetType() + " (" + expression + ")"); return(new VariableState(expression, VariableTaint.Unknown)); }
public virtual void VisitAssignment(VisualBasicSyntaxNode node, ExecutionState state, MethodBehavior behavior, ISymbol symbol, VariableState variableRightState) { }
/// <summary> /// Logic for each method invocation (including constructor) /// The argument list is required because <code>InvocationExpressionSyntax</code> and /// <code>ObjectCreationExpressionSyntax</code> do not share a common interface. /// </summary> /// <param name="node"></param> /// <param name="argList"></param> /// <param name="state"></param> /// <returns></returns> private VariableState VisitInvocationAndCreation(ExpressionSyntax node, ArgumentListSyntax argList, ExecutionState state, VariableState initialVariableState = null) { var symbol = state.GetSymbol(node); if (symbol == null) { return(new VariableState(node, VariableTaint.Unknown)); } var behavior = symbol.GetMethodBehavior(state.AnalysisContext.Options.AdditionalFiles); var returnState = initialVariableState != null && !symbol.IsStatic ? initialVariableState : new VariableState(node, behavior?.TaintFromArguments?.Any() == true ? VariableTaint.Safe : VariableTaint.Unknown); for (var i = 0; i < argList?.Arguments.Count; i++) { var argument = argList.Arguments[i]; var argumentState = VisitExpression(argument.GetExpression(), state); Logger.Log(symbol.ContainingType + "." + symbol.Name + " -> " + argumentState); if (behavior == null) { continue; } //If the API is at risk if ((argumentState.Taint == VariableTaint.Tainted || argumentState.Taint == VariableTaint.Unknown) && //Tainted values //If the current parameter can be injected. Array.Exists(behavior.InjectablesArguments, element => element == i)) { var newRule = LocaleUtil.GetDescriptor(behavior.LocaleInjection); var diagnostic = Diagnostic.Create(newRule, node.GetLocation(), GetMethodName(node), (i + 1).ToNthString()); state.AnalysisContext.ReportDiagnostic(diagnostic); } else if (argumentState.Taint == VariableTaint.Constant && //Hard coded value //If the current parameter is a password Array.Exists(behavior.PasswordArguments, element => element == i)) { var newRule = LocaleUtil.GetDescriptor(behavior.LocalePassword); var diagnostic = Diagnostic.Create(newRule, node.GetLocation(), GetMethodName(node), (i + 1).ToNthString()); state.AnalysisContext.ReportDiagnostic(diagnostic); } else if (Array.Exists(behavior.TaintFromArguments, element => element == i)) { returnState.Merge(argumentState); } //TODO: taint all objects passed as arguments } //Additional analysis by extension foreach (var ext in Extensions) { ext.VisitInvocationAndCreation(node, argList, state); } return(returnState); }
/// <summary> /// Statement are all segment separate by semi-colon. /// </summary> /// <param name="node"></param> /// <param name="state"></param> private VariableState VisitNode(SyntaxNode node, ExecutionState state) { switch (node) { case UnaryExpressionSyntax unaryExpressionSyntax: return(VisitNode(unaryExpressionSyntax.Operand, state)); case LocalDeclarationStatementSyntax localDeclaration: return(VisitLocalDeclaration(localDeclaration, state)); case VariableDeclaratorSyntax variableDeclaration: return(VisitVariableDeclaration(variableDeclaration, state)); case AssignmentStatementSyntax assignment: return(VisitAssignmentStatement(assignment, state)); case ExpressionStatementSyntax expressionStatement: return(VisitExpressionStatement(expressionStatement, state)); case ExpressionSyntax expression: return(VisitExpression(expression, state)); case MethodBlockSyntax methodBlock: return(VisitMethodDeclaration(methodBlock, methodBlock.SubOrFunctionStatement.ParameterList, state)); case ConstructorBlockSyntax constructorBlockSyntax: return(VisitMethodDeclaration(constructorBlockSyntax, constructorBlockSyntax.SubNewStatement.ParameterList, state)); case PropertyBlockSyntax propertyBlockSyntax: return(VisitPropertyBlock(propertyBlockSyntax, state)); case ReturnStatementSyntax returnStatementSyntax: if (returnStatementSyntax.Expression == null) { return(new VariableState(node, VariableTaint.Unknown)); } return(VisitExpression(returnStatementSyntax.Expression, state)); case ForEachStatementSyntax forEachSyntax: return(VisitForEach(forEachSyntax, state)); case FromClauseSyntax fromClauseSyntax: return(VisitFromClause(fromClauseSyntax, state)); case WhereClauseSyntax whereClauseSyntax: return(VisitExpression(whereClauseSyntax.Condition, state)); case SelectClauseSyntax selectClauseSyntax: return(VisitSelectClause(selectClauseSyntax, state)); case ExpressionRangeVariableSyntax expressionRangeVariableSyntax: return(VisitExpression(expressionRangeVariableSyntax.Expression, state)); case CollectionRangeVariableSyntax collectionRangeVariableSyntax: return(VisitCollectionRangeVariable(collectionRangeVariableSyntax, state)); case SingleLineIfStatementSyntax singleLineIfStatementSyntax: return(VisitSingleLineIfStatement(singleLineIfStatementSyntax, state)); case IfStatementSyntax ifStatementSyntax: return(VisitExpression(ifStatementSyntax.Condition, state)); case ElseBlockSyntax elseBlockSyntax: { var lastState = new VariableState(elseBlockSyntax, VariableTaint.Unset); return(VisitStatements(elseBlockSyntax.Statements, state, lastState)); } case ElseIfStatementSyntax elseIfStatementSyntax: return(VisitExpression(elseIfStatementSyntax.Condition, state)); case ElseIfBlockSyntax elseIfBlockSyntax: { var lastState = VisitNode(elseIfBlockSyntax.ElseIfStatement, state); return(VisitStatements(elseIfBlockSyntax.Statements, state, lastState)); } case MultiLineIfBlockSyntax multiLineIfBlockSyntax: return(VisitMultiLineIfBlock(multiLineIfBlockSyntax, state)); case SelectBlockSyntax selectBlockSyntax: return(VisitSelectBlock(selectBlockSyntax, state)); case SelectStatementSyntax selectStatementSyntax: return(VisitExpression(selectStatementSyntax.Expression, state)); case CaseBlockSyntax caseBlockSyntax: return(VisitStatements(caseBlockSyntax.Statements, state, new VariableState(caseBlockSyntax, VariableTaint.Unset))); } foreach (var n in node.ChildNodes()) { VisitNode(n, state); } var isBlockStatement = node is ForStatementSyntax || node is UsingStatementSyntax; if (!isBlockStatement) { #if DEBUG //throw new Exception("Unsupported statement " + node.GetType() + " (" + node + ")"); Logger.Log("Unsupported statement " + node.GetType() + " (" + node + ")"); #endif } return(new VariableState(node, VariableTaint.Unknown)); }
/// <summary> /// Logic for each method invocation (including constructor) /// The argument list is required because <code>InvocationExpressionSyntax</code> and /// <code>ObjectCreationExpressionSyntax</code> do not share a common interface. /// </summary> /// <param name="node"></param> /// <param name="argList"></param> /// <param name="state"></param> /// <returns></returns> private VariableState VisitInvocationAndCreation(ExpressionSyntax node, ArgumentListSyntax argList, ExecutionState state, VariableState initialVariableState = null) { var symbol = state.GetSymbol(node); if (symbol == null) { return(new VariableState(node, VariableTaint.Unknown)); } VariableState returnState; var behavior = symbol.GetMethodBehavior(state.AnalysisContext.Options.AdditionalFiles); if (behavior?.TaintFromArguments.Length == 1 && behavior.TaintFromArguments[0] == -1) { returnState = new VariableState(node, VariableTaint.Safe); } else { returnState = initialVariableState != null && !symbol.IsStatic ? initialVariableState : new VariableState(node, behavior?.TaintFromArguments?.Any() == true ? VariableTaint.Safe : VariableTaint.Unknown); } bool isExtensionMethod = (symbol as IMethodSymbol)?.ReducedFrom != null; for (var i = 0; i < argList?.Arguments.Count; i++) { var argument = argList.Arguments[i]; var argumentState = VisitExpression(argument.Expression, state); Logger.Log(symbol.ContainingType + "." + symbol.Name + " -> " + argumentState); if (behavior == null) { continue; } //If the API is at risk if ((argumentState.Taint == VariableTaint.Tainted || argumentState.Taint == VariableTaint.Unknown) && //Tainted values //If the current parameter can be injected. Array.Exists(behavior.InjectablesArguments, element => element == (isExtensionMethod ? i + 1 : i))) { var newRule = LocaleUtil.GetDescriptor(behavior.LocaleInjection); var diagnostic = Diagnostic.Create(newRule, node.GetLocation(), GetMethodName(node), (i + 1).ToNthString()); state.AnalysisContext.ReportDiagnostic(diagnostic); } else if (argumentState.Taint == VariableTaint.Constant && //Hard coded value //If the current parameter is a password Array.Exists(behavior.PasswordArguments, element => element == (isExtensionMethod ? i + 1 : i))) { var newRule = LocaleUtil.GetDescriptor(behavior.LocalePassword); var diagnostic = Diagnostic.Create(newRule, node.GetLocation(), GetMethodName(node), (i + 1).ToNthString()); state.AnalysisContext.ReportDiagnostic(diagnostic); } else if (Array.Exists(behavior.TaintFromArguments, element => element == (isExtensionMethod ? i + 1 : i))) { returnState.Merge(argumentState); } //TODO: taint all objects passed as arguments //if (argument.Expression is IdentifierNameSyntax identifierNameSyntax) //{ // var argumentType = state.AnalysisContext.SemanticModel.GetTypeInfo(argument.Expression).Type; // if (argumentType.IsReferenceType && // argumentType.IsType("System.String")) // string is immutable // { // state.MergeValue(ResolveIdentifier(identifierNameSyntax.Identifier), // argumentState.Merge(new VariableState(argument, VariableTaint.Unknown))); // } //} } //Additional analysis by extension foreach (var ext in Extensions) { ext.VisitInvocationAndCreation(node, argList, state); } return(returnState); }
/// <summary> /// Logic for each method invocation (including constructor) /// The argument list is required because <code>InvocationExpressionSyntax</code> and /// <code>ObjectCreationExpressionSyntax</code> do not share a common interface. /// </summary> /// <param name="node"></param> /// <param name="argList"></param> /// <param name="state"></param> /// <returns></returns> private VariableState VisitInvocationAndCreation(ExpressionSyntax node, ArgumentListSyntax argList, ExecutionState state) { var symbol = state.GetSymbol(node); MethodBehavior behavior = BehaviorRepo.GetMethodBehavior(symbol); int i = 0; if (argList == null) { return(new VariableState(node, VariableTaint.Unknown)); } var returnState = new VariableState(node, VariableTaint.Safe); foreach (var argument in argList.Arguments) { var argumentState = VisitExpression(argument.Expression, state); if (symbol != null) { Logger.Log(symbol.ContainingType + "." + symbol.Name + " -> " + argumentState); } if (behavior != null) { //If the API is at risk if ((argumentState.Taint == VariableTaint.Tainted || argumentState.Taint == VariableTaint.Unknown) && //Tainted values //If the current parameter can be injected. Array.Exists(behavior.InjectablesArguments, element => element == i)) { var newRule = LocaleUtil.GetDescriptor(behavior.LocaleInjection); var diagnostic = Diagnostic.Create(newRule, node.GetLocation()); state.AnalysisContext.ReportDiagnostic(diagnostic); } else if (argumentState.Taint == VariableTaint.Constant && //Hard coded value //If the current parameter is a password Array.Exists(behavior.PasswordArguments, element => element == i)) { var newRule = LocaleUtil.GetDescriptor(behavior.LocalePassword); var diagnostic = Diagnostic.Create(newRule, node.GetLocation()); state.AnalysisContext.ReportDiagnostic(diagnostic); } else if (Array.Exists(behavior.TaintFromArguments, element => element == i)) { returnState = returnState.Merge(argumentState); } } //TODO: tainted all object passed in argument i++; } //Additional analysis by extension foreach (var ext in Extensions) { ext.VisitInvocationAndCreation(node, argList, state); } var hasTaintFromArguments = behavior?.TaintFromArguments?.Length > 0; return(hasTaintFromArguments ? returnState : new VariableState(node, VariableTaint.Unknown)); }
private VariableState VisitBlock(MethodBlockBaseSyntax node, ExecutionState state) { var lastState = new VariableState(node, VariableTaint.Unknown); return(VisitStatements(node.Statements, state, lastState)); }
/// <summary> /// Logic for each method invocation (including constructor) /// The argument list is required because <code>InvocationExpressionSyntax</code> and /// <code>ObjectCreationExpressionSyntax</code> do not share a common interface. /// </summary> private VariableState VisitInvocationAndCreation(ExpressionSyntax node, ArgumentListSyntax argList, ExecutionState state, VariableTaint?initialTaint = null, VariableState memberVariableState = null) { var symbol = state.GetSymbol(node); if (symbol == null) { return(new VariableState(node, initialTaint ?? VariableTaint.Unknown)); } var methodSymbol = symbol as IMethodSymbol; bool isExtensionMethod = methodSymbol?.ReducedFrom != null; var behavior = symbol.GetMethodBehavior(ProjectConfiguration.Behavior); IReadOnlyDictionary <int, PostCondition> postConditions = null; if (behavior != null) { postConditions = GetPostConditions(behavior, isExtensionMethod, argList, state); } PostCondition returnPostCondition = null; postConditions?.TryGetValue(-1, out returnPostCondition); VariableState returnState = initialTaint != null && !symbol.IsStatic ? new VariableState(node, initialTaint.Value) : new VariableState(node, argList?.Arguments.Count > 0 && behavior != null ? VariableTaint.Unset : VariableTaint.Unknown); var argCount = argList?.Arguments.Count; var argumentStates = argCount.HasValue && argCount.Value > 0 && (postConditions?.Any(c => c.Key != -1 && (c.Value.Taint != 0ul || c.Value.TaintFromArguments.Any())) == true || methodSymbol != null && methodSymbol.Parameters.Any(x => x.RefKind != RefKind.None)) ? new VariableState[argCount.Value] : null; for (var i = 0; i < argList?.Arguments.Count; i++) { var argument = argList.Arguments[i]; var argumentState = VisitExpression(argument.GetExpression(), state); if (argumentStates != null) { argumentStates[i] = argumentState; } #if DEBUG Logger.Log(symbol.ContainingType + "." + symbol.Name + " -> " + argumentState); #endif var adjustedArgumentIdx = isExtensionMethod ? i + 1 : i; if (behavior != null) { if ((argumentState.Taint & (ProjectConfiguration.AuditMode ? VariableTaint.Tainted | VariableTaint.Unknown : VariableTaint.Tainted)) != 0) { //If the current parameter can be injected. if (behavior.InjectableArguments.TryGetValue(adjustedArgumentIdx, out var injectableArgument) && (injectableArgument.RequiredTaintBits & (ulong)argumentState.Taint) != injectableArgument.RequiredTaintBits) { var newRule = LocaleUtil.GetDescriptor(injectableArgument.Locale); var diagnostic = Diagnostic.Create(newRule, argument.GetExpression().GetLocation(), GetMethodName(node), (i + 1).ToNthString()); state.AnalysisContext.ReportDiagnostic(diagnostic); } } else if (argumentState.Taint == VariableTaint.Constant) { if (behavior.InjectableArguments.TryGetValue(adjustedArgumentIdx, out var injectableArgument) && injectableArgument.Not && (injectableArgument.RequiredTaintBits & (ulong)argumentState.Taint) != 0ul) { var newRule = LocaleUtil.GetDescriptor(injectableArgument.Locale); var diagnostic = Diagnostic.Create(newRule, argument.GetExpression().GetLocation(), GetMethodName(node), (i + 1).ToNthString()); state.AnalysisContext.ReportDiagnostic(diagnostic); } } } var argumentToSearch = adjustedArgumentIdx; if (methodSymbol != null && i >= methodSymbol.Parameters.Length && methodSymbol.Parameters[methodSymbol.Parameters.Length - 1].IsParams) { argumentToSearch = isExtensionMethod ? methodSymbol.Parameters.Length : methodSymbol.Parameters.Length - 1; } if (returnPostCondition == null || returnPostCondition.TaintFromArguments.Contains(argumentToSearch)) { returnState.MergeTaint(argumentState.Taint); } //TODO: taint all objects passed as arguments } if (returnPostCondition != null) { returnState.ApplyTaint(returnPostCondition.Taint); } if (argumentStates != null) { for (var i = 0; i < argList.Arguments.Count; i++) { var adjustedPostConditionIdx = isExtensionMethod ? i + 1 : i; if (postConditions != null && postConditions.TryGetValue(adjustedPostConditionIdx, out var postCondition)) { foreach (var argIdx in postCondition.TaintFromArguments) { var adjustedArgumentIdx = isExtensionMethod ? argIdx + 1 : argIdx; argumentStates[adjustedPostConditionIdx].MergeTaint(argumentStates[adjustedArgumentIdx].Taint); } argumentStates[adjustedPostConditionIdx].ApplyTaint(postCondition.Taint); } else if (methodSymbol != null) { if (i >= methodSymbol.Parameters.Length) { if (!methodSymbol.Parameters[methodSymbol.Parameters.Length - 1].IsParams) { throw new IndexOutOfRangeException(); } } else if (methodSymbol.Parameters[i].RefKind != RefKind.None) { argumentStates[i].MergeTaint(returnState.Taint); } } } } if (memberVariableState != null && methodSymbol != null && methodSymbol.ReturnsVoid && !methodSymbol.IsStatic && methodSymbol.Parameters.All(x => x.RefKind == RefKind.None)) { memberVariableState.MergeTaint(returnState.Taint); } //Additional analysis by extension foreach (var ext in Extensions) { ext.VisitInvocationAndCreation(node, argList, state); } return(returnState); }
public virtual void VisitAssignment(CSharpSyntax.AssignmentExpressionSyntax node, ExecutionState state, MethodBehavior behavior, ISymbol symbol, VariableState variableRightState) { }
private VariableState VisitExpression(ExpressionSyntax expression, ExecutionState state) { switch (expression) { case ParenthesizedExpressionSyntax parenthesizedExpressionSyntax: return(VisitExpression(parenthesizedExpressionSyntax.Expression, state)); case InvocationExpressionSyntax invocationExpressionSyntax: return(VisitMethodInvocation(invocationExpressionSyntax, state)); case ObjectCreationExpressionSyntax objectCreationExpressionSyntax: return(VisitObjectCreation(objectCreationExpressionSyntax, state)); case LiteralExpressionSyntax literalExpressionSyntax: return(new VariableState(literalExpressionSyntax, VariableTaint.Constant, literalExpressionSyntax.Token.Value)); case IdentifierNameSyntax identifierNameSyntax: return(VisitIdentifierName(identifierNameSyntax, state)); case BinaryExpressionSyntax binaryExpressionSyntax: { switch (binaryExpressionSyntax.Kind()) { case SyntaxKind.AsExpression: case SyntaxKind.IsExpression: return(VisitNode(binaryExpressionSyntax.Left, state)); } return(VisitBinaryExpression(binaryExpressionSyntax, binaryExpressionSyntax.Left, binaryExpressionSyntax.Right, state)); } case AssignmentExpressionSyntax assignmentExpressionSyntax: if (assignmentExpressionSyntax.Kind() != SyntaxKind.SimpleAssignmentExpression) { var left = VisitExpression(assignmentExpressionSyntax.Left, state); var assignmentState = VisitAssignment(assignmentExpressionSyntax, state); left.MergeTaint(assignmentState.Taint); return(left); } else { var assignmentState = VisitAssignment(assignmentExpressionSyntax, state); return(MergeVariableState(assignmentExpressionSyntax.Left, assignmentState, state)); } case MemberAccessExpressionSyntax memberAccessExpressionSyntax: return(VisitMemberAccessExpression(memberAccessExpressionSyntax, state)); case ElementAccessExpressionSyntax elementAccessExpressionSyntax: return(VisitElementAccess(elementAccessExpressionSyntax, elementAccessExpressionSyntax.ArgumentList, state)); case ArrayCreationExpressionSyntax arrayCreationExpressionSyntax: return(VisitArrayCreation(arrayCreationExpressionSyntax, arrayCreationExpressionSyntax.Initializer, state)); case ImplicitArrayCreationExpressionSyntax implicitArrayCreationExpressionSyntax: return(VisitArrayCreation(implicitArrayCreationExpressionSyntax, implicitArrayCreationExpressionSyntax.Initializer, state)); case TypeOfExpressionSyntax typeOfExpressionSyntax: return(new VariableState(typeOfExpressionSyntax, VariableTaint.Safe)); case ConditionalExpressionSyntax conditionalExpressionSyntax: { VisitExpression(conditionalExpressionSyntax.Condition, state); var finalState = new VariableState(conditionalExpressionSyntax, VariableTaint.Unset); var whenTrueState = VisitExpression(conditionalExpressionSyntax.WhenTrue, state); finalState.MergeTaint(whenTrueState.Taint); var whenFalseState = VisitExpression(conditionalExpressionSyntax.WhenFalse, state); finalState.MergeTaint(whenFalseState.Taint); return(finalState); } case CheckedExpressionSyntax checkedExpressionSyntax: return(VisitExpression(checkedExpressionSyntax.Expression, state)); case QueryExpressionSyntax queryExpressionSyntax: { var finalState = new VariableState(queryExpressionSyntax, VariableTaint.Unset); var fromState = VisitNode(queryExpressionSyntax.FromClause, state); finalState.MergeTaint(fromState.Taint); var bodyState = VisitNode(queryExpressionSyntax.Body, state); finalState.MergeTaint(bodyState.Taint); return(finalState); } case InterpolatedStringExpressionSyntax interpolatedStringExpressionSyntax: return(VisitInterpolatedString(interpolatedStringExpressionSyntax, state)); case CastExpressionSyntax castExpressionSyntax: return(VisitExpression(castExpressionSyntax.Expression, state)); case DefaultExpressionSyntax defaultExpressionSyntax: var value = state.AnalysisContext.SemanticModel.GetConstantValue(defaultExpressionSyntax); return(new VariableState(defaultExpressionSyntax, VariableTaint.Constant, value.HasValue ? value.Value : null)); case PrefixUnaryExpressionSyntax prefixUnaryExpressionSyntax: return(VisitExpression(prefixUnaryExpressionSyntax.Operand, state)); } #if DEBUG Logger.Log("Unsupported expression " + expression.GetType() + " (" + expression + ")"); #endif return(new VariableState(expression, VariableTaint.Unknown)); }