private VariableState VisitAssignment(AssignmentExpressionSyntax node, ExecutionState state)
        {
            var            symbol   = state.GetSymbol(node.Left);
            MethodBehavior behavior = behaviorRepo.GetMethodBehavior(symbol);

            var variableState = VisitExpression(node.Right, state);

            //Additionnal analysis by extension
            foreach (var ext in extensions)
            {
                ext.VisitAssignment(node, state, behavior, symbol, variableState);
            }

            IdentifierNameSyntax parentIdentifierSyntax = GetParentIdentifier(node.Left);

            if (parentIdentifierSyntax != null)
            {
                state.MergeValue(ResolveIdentifier(parentIdentifierSyntax.Identifier), variableState);
            }

            if (behavior != null &&                              //Injection
                behavior.isInjectableField &&
                variableState.taint != VariableTaint.CONSTANT && //Skip safe values
                variableState.taint != VariableTaint.SAFE)
            {
                var newRule    = LocaleUtil.GetDescriptor(behavior.localeInjection);
                var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                state.AnalysisContext.ReportDiagnostic(diagnostic);
            }
            if (behavior != null &&                           //Known Password API
                behavior.isPasswordField &&
                variableState.taint == VariableTaint.CONSTANT //Only constant
                )
            {
                var newRule    = LocaleUtil.GetDescriptor(behavior.localePassword);
                var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                state.AnalysisContext.ReportDiagnostic(diagnostic);
            }


            //TODO: tainted the variable being assign.


            return(variableState);
        }
Exemple #2
0
        private VariableState VisitAssignment(AssignmentExpressionSyntax node, ExecutionState state)
        {
            var            leftSymbol = state.GetSymbol(node.Left);
            MethodBehavior behavior   = null;

            if (leftSymbol != null)
            {
                behavior = leftSymbol.GetMethodBehavior(ProjectConfiguration.Behavior);
            }

            var variableState = VisitExpression(node.Right, state);

            //Additional analysis by extension
            foreach (var ext in Extensions)
            {
                ext.VisitAssignment(node, state, behavior, leftSymbol, variableState);
            }

            //if (leftSymbol != null)
            //{
            //    var rightTypeSymbol = state.AnalysisContext.SemanticModel.GetTypeInfo(node.Right).Type;
            //    if (rightTypeSymbol == null)
            //        return new VariableState(node.Right, VariableTaint.Unknown);

            //    var leftTypeSymbol = state.AnalysisContext.SemanticModel.GetTypeInfo(node.Left).Type;
            //    if (!state.AnalysisContext.SemanticModel.Compilation.ClassifyConversion(rightTypeSymbol, leftTypeSymbol).IsImplicit)
            //        return new VariableState(node.Right, VariableTaint.Unknown);
            //}

            if (variableState.Taint != VariableTaint.Constant &&
                behavior != null &&
                // compare if all required sanitization bits are set
                ((ulong)(variableState.Taint & VariableTaint.Safe) & behavior.InjectableField.RequiredTaintBits) != behavior.InjectableField.RequiredTaintBits &&
                (variableState.Taint & (ProjectConfiguration.AuditMode ? VariableTaint.Tainted | VariableTaint.Unknown : VariableTaint.Tainted)) != 0)
            {
                var newRule    = LocaleUtil.GetDescriptor(behavior.InjectableField.Locale, "title_assignment");
                var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                state.AnalysisContext.ReportDiagnostic(diagnostic);
            }

            //TODO: taint the variable being assigned.

            return(variableState);
        }
        private VariableState VisitAssignment(AssignmentExpressionSyntax node, ExecutionState state)
        {
            var            symbol   = state.GetSymbol(node.Left);
            MethodBehavior behavior = behaviorRepo.GetInjectableMethodBehavior(symbol);

            var variableState = VisitExpression(node.Right, state);

            if (node.Left is IdentifierNameSyntax)
            {
                var assignmentIdentifier = node.Left as IdentifierNameSyntax;
                state.UpdateValue(ResolveIdentifier(assignmentIdentifier.Identifier), variableState);
            }

            if (behavior != null &&                              //If the API is at risk
                variableState.taint != VariableTaint.CONSTANT && //Skip safe values
                variableState.taint != VariableTaint.SAFE)
            {
                var newRule    = LocaleUtil.GetDescriptor(behavior.vulnerabilityLocale);
                var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                state.AnalysisContext.ReportDiagnostic(diagnostic);
            }

            return(variableState);
        }
        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.GetExpression(), state);

                if (symbol != null)
                {
                    SGLogging.Log(symbol.ContainingType + "." + symbol.Name + " -> " + argumentState);
                }

                if (behavior != null)
                {                                                                            //If the API is at risk
                    if ((argumentState.taint == VariableTaint.TAINTED ||                     //Tainted values
                         argumentState.taint == VariableTaint.UNKNOWN) &&
                        Array.Exists(behavior.injectablesArguments, element => element == i) //If the current parameter can be injected.
                        )
                    {
                        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
                             Array.Exists(behavior.passwordArguments, element => element == i) //If the current parameter is a password
                             )
                    {
                        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++;
            }

            //Additionnal analysis by extension
            foreach (var ext in extensions)
            {
                ext.VisitInvocationAndCreation(node, argList, state);
            }

            var hasTaintFromArguments = behavior?.taintFromArguments?.Length > 0;

            if (hasTaintFromArguments)
            {
                return(returnState);
            }
            else
            {
                return(new VariableState(node, VariableTaint.UNKNOWN));
            }
        }
Exemple #5
0
        private VariableState VisitAssignment(AssignmentExpressionSyntax node, ExecutionState state)
        {
            var            leftSymbol = state.GetSymbol(node.Left);
            MethodBehavior behavior   = null;

            if (leftSymbol != null)
            {
                behavior = leftSymbol.GetMethodBehavior(state.AnalysisContext.Options.AdditionalFiles);
            }

            var variableState = VisitExpression(node.Right, state);

            //Additional analysis by extension
            foreach (var ext in Extensions)
            {
                ext.VisitAssignment(node, state, behavior, leftSymbol, variableState);
            }

            if (leftSymbol != null)
            {
                var rightTypeSymbol = state.AnalysisContext.SemanticModel.GetTypeInfo(node.Right).Type;
                if (rightTypeSymbol == null)
                {
                    return(new VariableState(node.Right, VariableTaint.Unknown));
                }

                var leftTypeSymbol = state.AnalysisContext.SemanticModel.GetTypeInfo(node.Left).Type;
                if (!state.AnalysisContext.SemanticModel.Compilation.ClassifyConversion(rightTypeSymbol, leftTypeSymbol).IsImplicit)
                {
                    return(new VariableState(node.Right, VariableTaint.Unknown));
                }
            }

            IdentifierNameSyntax parentIdentifierSyntax = GetParentIdentifier(node.Left);

            if (parentIdentifierSyntax != null)
            {
                state.MergeValue(ResolveIdentifier(parentIdentifierSyntax.Identifier), variableState);
            }

            if (behavior != null &&                              //Injection
                behavior.IsInjectableField &&
                variableState.Taint != VariableTaint.Constant && //Skip safe values
                variableState.Taint != VariableTaint.Safe)
            {
                var newRule    = LocaleUtil.GetDescriptor(behavior.LocaleInjection, "title_assignment");
                var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                state.AnalysisContext.ReportDiagnostic(diagnostic);
            }

            if (behavior != null &&                            //Known Password API
                behavior.IsPasswordField &&
                variableState.Taint == VariableTaint.Constant) //Only constant
            {
                var newRule    = LocaleUtil.GetDescriptor(behavior.LocalePassword, "title_assignment");
                var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                state.AnalysisContext.ReportDiagnostic(diagnostic);
            }

            //TODO: taint the variable being assigned.

            return(variableState);
        }
Exemple #6
0
        /// <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.HasValue && !symbol.IsStatic
                                  ? initialVariableState.Value
                                  : 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.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 == 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 = 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);
        }
        public void LoadConfiguration(string configurationFile)
        {
            var assembly = typeof(MethodBehaviorRepository).GetTypeInfo().Assembly;

            using (Stream stream = assembly.GetManifestResourceStream("RoslynSecurityGuard.Config." + configurationFile))
                using (StreamReader reader = new StreamReader(stream))
                {
                    var yaml = new YamlStream();
                    yaml.Load(reader);

                    var mapping = (YamlMappingNode)yaml.Documents[0].RootNode;

                    foreach (var entry in mapping.Children)
                    {
                        var key   = (YamlScalarNode)entry.Key;
                        var value = (YamlMappingNode)entry.Value;

                        //The behavior structure allows the configuration of injectable arguments and password field
                        //This is the reason. The format merges the two concepts.

                        //Loading the properties for each entry
                        string beNamespace = GetField(entry, "namespace", true);
                        string beClassName = GetField(entry, "className", true);
                        string beMember    = GetField(entry, "member", true);
                        string beName      = GetField(entry, "name", true);
                        //--Method behavior
                        string beInjectableArguments = GetField(entry, "injectableArguments", defaultValue: "");
                        string bePasswordArguments   = GetField(entry, "passwordArguments", defaultValue: "");
                        string beArgTypes            = GetField(entry, "argTypes");
                        //--Field behavior
                        bool beInjectableField = bool.Parse(GetField(entry, "injectableField", defaultValue: "false"));
                        bool bePasswordField   = bool.Parse(GetField(entry, "passwordField", defaultValue: "false"));
                        //--Localisation
                        string beLocale     = GetField(entry, "locale");
                        string beLocalePass = GetField(entry, "localePass");

                        string beTaintFromArguments = GetField(entry, "taintFromArguments", defaultValue: "");


                        //Converting the list of index to array
                        int[] argumentsIndexes          = convertToIntArray(beInjectableArguments.Split(','));
                        int[] passwordIndexes           = convertToIntArray(bePasswordArguments.Split(','));
                        int[] taintFromArgumentsIndexes = convertToIntArray(beTaintFromArguments.Split(','));

                        foreach (var locale in new string[] { beLocale, beLocalePass })
                        {
                            if (locale != null && !descriptors.ContainsKey(locale))
                            {
                                descriptors.Add(locale, LocaleUtil.GetDescriptor(locale));
                            }
                        }


                        //Validate that 'argumentsIndexes' field
                        if ((!beInjectableField && !bePasswordField) && //Not a field signatures, arguments indexes is expected.
                            argumentsIndexes.Length == 0 &&
                            passwordIndexes.Length == 0 &&
                            taintFromArgumentsIndexes.Length == 0)
                        {
                            throw new Exception("The method behavior " + key + " is not missing injectableArguments or passwordArguments property");
                        }

                        //Injection based vulnerability
                        string globalKey = beArgTypes != null ?                                                  //
                                           (beNamespace + "." + beClassName + "|" + beName + "|" + beArgTypes) : //With arguments types discriminator
                                           (beNamespace + "." + beClassName + "|" + beName);                     //Minimalist configuration


                        methodInjectableArguments.Add(globalKey,
                                                      new MethodBehavior(argumentsIndexes, passwordIndexes, taintFromArgumentsIndexes,
                                                                         beLocale, beLocalePass, beInjectableField, bePasswordField));


                        //SGLogging.Log(beNamespace);
                    }

                    //SGLogging.Log(methodInjectableArguments.Count + " signatures loaded.");
                }
        }
        public void LoadConfiguration(string configurationFile)
        {
            var assembly = typeof(MethodBehaviorRepository).GetTypeInfo().Assembly;

            using (Stream stream = assembly.GetManifestResourceStream("RoslynSecurityGuard." + configurationFile))
                using (StreamReader reader = new StreamReader(stream))
                {
                    var yaml = new YamlStream();
                    yaml.Load(reader);

                    var mapping = (YamlMappingNode)yaml.Documents[0].RootNode;

                    foreach (var entry in mapping.Children)
                    {
                        var key   = (YamlScalarNode)entry.Key;
                        var value = (YamlMappingNode)entry.Value;

                        //Loading the properties for each entry
                        string beNamespace           = ((YamlScalarNode)value.Children[new YamlScalarNode("namespace")]).Value;
                        string beClassName           = ((YamlScalarNode)value.Children[new YamlScalarNode("className")]).Value;
                        string beMember              = ((YamlScalarNode)value.Children[new YamlScalarNode("member")]).Value;
                        string beName                = ((YamlScalarNode)value.Children[new YamlScalarNode("name")]).Value;
                        string beInjectableArguments = "";
                        try
                        {
                            beInjectableArguments = ((YamlScalarNode)value.Children[new YamlScalarNode("injectableArguments")]).Value;
                        }
                        catch (KeyNotFoundException) { }
                        string bePasswordArguments = "";
                        try
                        {
                            bePasswordArguments = ((YamlScalarNode)value.Children[new YamlScalarNode("passwordArguments")]).Value;
                        }
                        catch (KeyNotFoundException) { }
                        string beArgTypes = null;
                        try
                        {
                            beArgTypes = ((YamlScalarNode)value.Children[new YamlScalarNode("argTypes")]).Value.Trim();
                        }
                        catch (KeyNotFoundException) { }
                        string beLocale = ((YamlScalarNode)value.Children[new YamlScalarNode("locale")]).Value;

                        //Converting the list of index to array
                        int[] argumentsIndexes = convertToIntArray(beInjectableArguments.Split(','));
                        int[] passwordIndexes  = convertToIntArray(bePasswordArguments.Split(','));

                        if (!descriptors.ContainsKey(beLocale))
                        {
                            var newDescriptor = LocaleUtil.GetDescriptor(beLocale);
                            descriptors.Add(beLocale, newDescriptor);
                        }

                        if (argumentsIndexes.Length == 0 && passwordIndexes.Length == 0)
                        {
                            throw new Exception("The method behavior " + key + " is not missing injectableArguments or passwordArguments property");
                        }

                        //Injection based vulnerability
                        if (beArgTypes != null)
                        {
                            methodInjectableArguments.Add(beNamespace + "." + beClassName + "|" + beName + "|" + beArgTypes, new MethodBehavior(argumentsIndexes, passwordIndexes, beLocale));
                        }
                        else
                        {
                            methodInjectableArguments.Add(beNamespace + "." + beClassName + "|" + beName, new MethodBehavior(argumentsIndexes, passwordIndexes, beLocale));
                        }


                        //SGLogging.Log(beNamespace);
                    }

                    //SGLogging.Log(methodInjectableArguments.Count + " signatures loaded.");
                }
        }
        /// <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);
        }
        /// <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));
        }
Exemple #11
0
        public void LoadDiagnosticLocale()
        {
            DiagnosticDescriptor desc = LocaleUtil.GetDescriptor("SCS0001");

            Console.WriteLine("Description: " + desc.Description);
        }
        /// <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.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 == (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
            }

            //Additional analysis by extension
            foreach (var ext in Extensions)
            {
                ext.VisitInvocationAndCreation(node, argList, state);
            }

            return(returnState);
        }