ASP.NET请求验证原因:是否有列表?

TK-*_*421 28 .net c# asp.net

是否有人知道触发ASP.NET的HttpRequestValidationException的确切原因列表?[这是常见错误的背后:"检测到潜在危险的Request.Form值,"等等]

我已经在这里检查过,在网上和MSDN库中都找不到这个记录.我知道一些生成错误的方法,但是希望有一个完整的列表,以便我可以防范并有选择地绕过它(我知道如何禁用页面的请求验证,但这不是一个选项案件).

这是"通过默默无闻的安全"的案例吗?

谢谢.

[注意:在IE8中不会为我加载脚本(如在Meta论坛中经常描述的那样),所以我将无法"添加评论."]

编辑1:您好Oded,您是否知道列出用于确定"潜在恶意输入字符串"的条件的列表?这就是我在寻找的东西.

编辑2:@Chris Pebble:是的,你说的.:)

Tra*_*lig 37

我找不到描述结论性列表的文档,但是通过Reflector查看并对HttpRequestValidationException的使用进行了一些分析,看起来下面的验证错误会导致请求验证失败:

  • 其中一个文件中的文件名张贴到上传.
  • 传入请求原始URL.
  • 来自任何传入cookie的名称/值对的值部分.
  • 来自通过GET/POST进入的任何字段的名称/值对的值部分.

那么,问题是"将这些事物中的一项视为危险的投入?" 这似乎发生在内部方法System.Web.CrossSiteScriptingValidation.IsDangerousString(string,out int)看起来像这样决定:

  1. 寻找<&在价值中.如果它不存在,或者它是值中的最后一个字符,则该值为OK.
  2. 如果&角色在一个&#序列中(例如,&#160;对于一个不间断的空间),那么它就是一个"危险的字符串".
  3. 如果<字符的一部分<x(其中"x"是任何英文字母AZ) <!,</或者<?,这是一个"危险的字符串."
  4. 如果失败了,价值就没问题了.

System.Web.CrossSiteScriptingValidation类型似乎有其他方法用于确定事物是危险的URL还是有效的JavaScript ID,但至少通过Reflector分析,这些方法不会出现,导致抛出HttpRequestValidationExceptions.


The*_*att 16

更新:

警告:原始答案(下面)中代码的某些部分已删除并标记为"已废弃".

Microsoft站点中的最新源代码(具有语法突出显示):

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

检查最新代码后,您可能会同意Travis Illig解释的是2018年现在使用的唯一验证(并且自2014 年GitHub中发布源代码后似乎没有任何更改).但是,如果您使用旧版本的框架,下面的旧代码可能仍然相关.


原答案:

使用Reflector,我做了一些浏览.这是原始代码.当我有时间时,我会将其转化为一些有意义的规则:

HttpRequestValidationException由只在一个单一的方法抛出System.Web的命名空间,所以它是相当孤立.这是方法:

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的IsDangerousString方法调用了CrossSiteScriptingValidation类中的方法,该方法根据一系列规则验证字符串.它看起来如下:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

IsDangerousString方法似乎引用了一系列验证规则,概述如下:

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);
}
Run Code Online (Sandbox Code Playgroud)

-

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] == '='));
}
Run Code Online (Sandbox Code Playgroud)

-

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

-

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] == ':'));
}
Run Code Online (Sandbox Code Playgroud)

所以你有它.破译并不是很好,但它就在那里.