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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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);
        }
Beispiel #9
0
        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);
            }
        }
Beispiel #12
0
        /// <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));
        }
Beispiel #14
0
 public void AddProperty(string identifier, VariableState secondState)
 {
     Properties.Add(identifier, secondState);
 }
Beispiel #15
0
 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));
        }
Beispiel #17
0
 public virtual void VisitStatement(VBSyntax.StatementSyntax node,
                                    ExecutionState state,
                                    VariableState statementState,
                                    Configuration projectConfiguration)
 {
 }
Beispiel #18
0
        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);
            }
        }
Beispiel #21
0
        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)
 {
 }
Beispiel #30
0
        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));
        }