ASP.NET request validation causes: is there a list?

后端 未结 6 1707
小鲜肉
小鲜肉 2020-12-08 14:26

is anybody aware of a list of exactly what triggers ASP.NET\'s HttpRequestValidationException? [This is behind the common error: \"A potentially dangerous Request.Form value

6条回答
  •  南方客
    南方客 (楼主)
    2020-12-08 14:55

    Update:

    Warning: Some parts of the code in the original answer (below) were removed and marked as OBSOLETE.

    Latest source code in Microsoft site (has syntax highlighting):

    http://referencesource.microsoft.com/#System.Web/CrossSiteScriptingValidation.cs

    After checking the newest code you will probably agree that what Travis Illig explained are the only validations used now in 2018 (and seems to have no changes since 2014 when the source was released in GitHub). But the old code below may still be relevant if you use an older version of the framework.


    Original Answer:

    Using Reflector, I did some browsing. Here's the raw code. When I have time I will translate this into some meaningful rules:

    The HttpRequestValidationException is thrown by only a single method in the System.Web namespace, so it's rather isolated. Here is the method:

    private void ValidateString(string s, string valueName, string collectionName)
    {
        int matchIndex = 0;
        if (CrossSiteScriptingValidation.IsDangerousString(s, out matchIndex))
        {
            string str = valueName + "=\"";
            int startIndex = matchIndex - 10;
            if (startIndex <= 0)
            {
                startIndex = 0;
            }
            else
            {
                str = str + "...";
            }
            int length = matchIndex + 20;
            if (length >= s.Length)
            {
                length = s.Length;
                str = str + s.Substring(startIndex, length - startIndex) + "\"";
            }
            else
            {
                str = str + s.Substring(startIndex, length - startIndex) + "...\"";
            }
            throw new HttpRequestValidationException(HttpRuntime.FormatResourceString("Dangerous_input_detected", collectionName, str));
        }
    }
    

    That method above makes a call to the IsDangerousString method in the CrossSiteScriptingValidation class, which validates the string against a series of rules. It looks like the following:

    internal static bool IsDangerousString(string s, out int matchIndex)
    {
        matchIndex = 0;
        int startIndex = 0;
        while (true)
        {
            int index = s.IndexOfAny(startingChars, startIndex);
            if (index < 0)
            {
                return false;
            }
            if (index == (s.Length - 1))
            {
                return false;
            }
            matchIndex = index;
            switch (s[index])
            {
                case 'E':
                case 'e':
                    if (IsDangerousExpressionString(s, index))
                    {
                        return true;
                    }
                    break;
    
                case 'O':
                case 'o':
                    if (!IsDangerousOnString(s, index))
                    {
                        break;
                    }
                    return true;
    
                case '&':
                    if (s[index + 1] != '#')
                    {
                        break;
                    }
                    return true;
    
                case '<':
                    if (!IsAtoZ(s[index + 1]) && (s[index + 1] != '!'))
                    {
                        break;
                    }
                    return true;
    
                case 'S':
                case 's':
                    if (!IsDangerousScriptString(s, index))
                    {
                        break;
                    }
                    return true;
            }
            startIndex = index + 1;
        }
    }
    

    That IsDangerousString method appears to be referencing a series of validation rules, which are outlined below:

    private static bool IsDangerousExpressionString(string s, int index)
    {
        if ((index + 10) >= s.Length)
        {
            return false;
        }
        if ((s[index + 1] != 'x') && (s[index + 1] != 'X'))
        {
            return false;
        }
        return (string.Compare(s, index + 2, "pression(", 0, 9, true, CultureInfo.InvariantCulture) == 0);
    }
    

    -

    private static bool IsDangerousOnString(string s, int index)
    {
        if ((s[index + 1] != 'n') && (s[index + 1] != 'N'))
        {
            return false;
        }
        if ((index > 0) && IsAtoZ(s[index - 1]))
        {
            return false;
        }
        int length = s.Length;
        index += 2;
        while ((index < length) && IsAtoZ(s[index]))
        {
            index++;
        }
        while ((index < length) && char.IsWhiteSpace(s[index]))
        {
            index++;
        }
        return ((index < length) && (s[index] == '='));
    }
    

    -

    private static bool IsAtoZ(char c)
    {
        return (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')));
    }
    

    -

    private static bool IsDangerousScriptString(string s, int index)
    {
        int length = s.Length;
        if ((index + 6) >= length)
        {
            return false;
        }
        if ((((s[index + 1] != 'c') && (s[index + 1] != 'C')) || ((s[index + 2] != 'r') && (s[index + 2] != 'R'))) || ((((s[index + 3] != 'i') && (s[index + 3] != 'I')) || ((s[index + 4] != 'p') && (s[index + 4] != 'P'))) || ((s[index + 5] != 't') && (s[index + 5] != 'T'))))
        {
            return false;
        }
        index += 6;
        while ((index < length) && char.IsWhiteSpace(s[index]))
        {
            index++;
        }
        return ((index < length) && (s[index] == ':'));
    }
    

    So there you have it. It's not pretty to decipher, but it's all there.

提交回复
热议问题