简体   繁体   English

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

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

is anybody aware of a list of exactly what triggers ASP.NET's HttpRequestValidationException? 是否有人知道触发ASP.NET的HttpRequestValidationException的确切原因列表? [This is behind the common error: "A potentially dangerous Request.Form value was detected," etc.] [这是常见错误的背后:“检测到潜在危险的Request.Form值,”等等]

I've checked here, around the Web, and MSDN Library but can't find this documented. 我已经在这里检查过,在网上和MSDN库中都找不到这个记录。 I'm aware of some ways to generate the error, but would like to have a complete list so I can guard against and selectively circumvent it (I know how to disable request validation for a page, but this isn't an option in this case). 我知道一些生成错误的方法,但是希望有一个完整的列表,以便我可以防范并有选择地绕过它(我知道如何禁用页面的请求验证,但这不是一个选项案件)。

Is it a case of "security through obscurity"? 这是“通过默默无闻的安全”的案例吗?

Thanks. 谢谢。

[Note: Scripts won't load for me in IE8 (as described frequently in the Meta forum) so I won't be able to "Add comment."] [注意:在IE8中不会为我加载脚本(如在Meta论坛中经常描述的那样),所以我将无法“添加评论。”]

EDIT 1: Hi Oded, are you aware of a list that documents the conditions used to determine a "potentially malicious input string"? 编辑1:您好Oded,您是否知道列出用于确定“潜在恶意输入字符串”的条件的列表? That's what I'm looking for. 这就是我在寻找的东西。

EDIT 2: @Chris Pebble: Yeah, what you said. 编辑2:@Chris Pebble:是的,你说的。 :) :)

I couldn't find a document outlining a conclusive list, but looking through Reflector and doing some analysis on use of HttpRequestValidationException, it looks like validation errors on the following can cause the request validation to fail: 我找不到一个描述结论性列表的文档,但是通过Reflector查看并使用HttpRequestValidationException进行一些分析,看起来下面的验证错误会导致请求验证失败:

  • A filename in one of the files POSTed to an upload. 其中一个文件中的文件名张贴到上传。
  • The incoming request raw URL. 传入请求原始URL。
  • The value portion of the name/value pair from any of the incoming cookies. 来自任何传入cookie的名称/值对的值部分。
  • The value portion of the name/value pair from any of the fields coming in through GET/POST. 来自通过GET / POST进入的任何字段的名称/值对的值部分。

The question, then, is "what qualifies one of these things as a dangerous input?" 那么,问题是“将这些事物中的一项视为危险的投入?” That seems to happen during an internal method System.Web.CrossSiteScriptingValidation.IsDangerousString(string, out int) which looks like it decides this way: 这似乎发生在内部方法System.Web.CrossSiteScriptingValidation.IsDangerousString(string,out int)看起来像这样决定:

  1. Look for < or & in the value. 在值中查找<& If it's not there, or if it's the last character in the value, then the value is OK. 如果它不存在,或者它是值中的最后一个字符,则该值为OK。
  2. If the & character is in a &# sequence (eg, &#160; for a non-breaking space), it's a "dangerous string." 如果&字符在&#序列中(例如, &#160;对于非中断空格),则它是“危险字符串”。
  3. If the < character is part of <x (where "x" is any alphabetic character az), <! 如果<字符是<x一部分(其中“x”是任何字母字符az), <! , </ , or <? </<? , it's a "dangerous string." ,这是一个“危险的字符串”。
  4. Failing all of that, the value is OK. 如果失败了,价值就没问题了。

The System.Web.CrossSiteScriptingValidation type seems to have other methods in it for determining if things are dangerous URLs or valid JavaScript IDs, but those don't appear, at least through Reflector analysis, to result in throwing HttpRequestValidationExceptions. System.Web.CrossSiteScriptingValidation类型似乎有其他方法来确定事物是危险的URL还是有效的JavaScript ID,但至少通过Reflector分析不会出现这些方法导致抛出HttpRequestValidationExceptions。

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): Microsoft网站中的最新源代码(具有语法突出显示):

http://referencesource.microsoft.com/#System.Web/CrossSiteScriptingValidation.cs 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 ). 检查最新代码后,您可能会同意Travis Illig解释的是2018年现在使用的唯一验证(并且自2014 年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. 使用Reflector,我做了一些浏览。 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. HttpRequestValidationException仅由System.Web命名空间中的单个方法抛出,因此它相当孤立。 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. 上面的方法调用CrossSiteScriptingValidation类中的IsDangerousString方法,该方法根据一系列规则验证字符串。 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: 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);
}

- -

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. 破译并不是很好,但它就在那里。

How about this script? 这个脚本怎么样? Your code can not detect this script, right? 你的代码无法检测到这个脚本,对吗?

";}alert(1);function%20a(){//

Try this regular expresson pattern. 试试这种常规表达模式。

You may need to ecape the \\ for javascript ex \\\\ 你可能需要为了javascript ex \\\\而逃离\\

var regExpPattern = '[eE][xX][pP][rR][eE][sS][sS][iI][oO][nN]\\(|\\b[oO][nN][a-zA-Z]*\\b\\s*=|&#|<[!/a-zA-Z]|[sS][cC][rR][iI][pP][tT]\\s*:';
var re = new RegExp("","gi");
re.compile(regExpPattern,"gi");
var outString = null;
outString = re.exec(text);

Following on from Travis' answer, the list of 'dangerous' character sequences can be simplified as follows; 根据特拉维斯的回答,“危险”字符序列列表可以简化如下;

  • &# &#
  • <A through to <Z (upper and lower case) <A到<Z(大小写)
  • <! <!
  • </ </
  • <? <?

Based on this, in an ASP.Net MVC web app the following Regex validation attribute can be used on a model field to trigger client side validation before an HttpRequestValidationException is thrown when the form is submitted; 基于此,在ASP.Net MVC Web应用程序中,可以在模型字段上使用以下Regex验证属性,以便在提交表单时抛出HttpRequestValidationException之前触发客户端验证;

[RegularExpression(@"^(?![\s\S]*(&#|<[a-zA-Z!\/?]))[\s\S]*$", ErrorMessage = "This field does not support HTML or allow any of the following character sequences; &quot;&amp;#&quot;, &quot;&lt;A&quot; through to &quot;&lt;Z&quot; (upper and lower case), &quot;&lt;!&quot;, &quot;&lt;/&quot; or &quot;&lt;?&quot;.")]

Note that validation attribute error messages are HTML encoded when output by server side validation, but not when used in client side validation, so this one is already encoded as we only intend to see it with client side validation. 请注意,验证属性错误消息在通过服务器端验证输出时是HTML编码的,但在客户端验证中使用时则不是,因此这个已经编码,因为我们只打算通过客户端验证来查看它。

From MSDN : 来自MSDN

'The exception that is thrown when a potentially malicious input string is received from the client as part of the request data. '作为请求数据的一部分从客户端收到潜在恶意输入字符串时引发的异常。 '

Many times this happens when JavaScript changes the values of a server side control in a way that causes the ViewState to not agree with the posted data. 很多时候,当JavaScript以一种导致ViewState与发布数据不一致的方式更改服务器端控件的值时,会发生这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM