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

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

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

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

谢谢。

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

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

编辑2:@Chris Pebble:是的,你说的。 🙂

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

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

那么,问题是“将这些东西中的哪一个作为危险的输入?” 这似乎发生在内部方法System.Web.CrossSiteScriptingValidation.IsDangerousString(string,out int)看起来像这样决定:

  1. 在值中查找<& 。 如果它不存在,或者它是值中的最后一个字符,则该值为OK。
  2. 如果&字符在&#序列中(例如,  对于非中断空格),则它是“危险字符串”。
  3. 如果<字符是 (其中“x”是任何字母字符az)的一部分, ,这是一个“危险的字符串”。
  4. 如果失败了,价值就没问题。

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

更新:

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

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

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

在检查了最新的代码之后,您可能会同意Travis Illig所解释的是2018年现在使用的唯一validation(并且自从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)); } } 

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

 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; } } 

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

 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] == ':')); } 

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

这个剧本怎么样? 你的代码无法检测到这个脚本,对吗?

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

试试这种常规的表达模式。

你可能需要为了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); 

来自MSDN :

‘作为请求数据的一部分从客户端收到潜在恶意输入字符串时引发的exception。 “

很多时候,当JavaScript以一种导致ViewState与发布数据不一致的方式更改服务器端控件的值时,会发生这种情况。