如何处理“从客户端检测到潜在危险的 Request.Form 值”?
Posted
技术标签:
【中文标题】如何处理“从客户端检测到潜在危险的 Request.Form 值”?【英文标题】:How to handle "A potentially dangerous Request.Form value was detected from the client"? 【发布时间】:2022-01-01 19:22:06 【问题描述】:我在 ASP.NET MVC Framework 应用程序的 protected void Application_Error()
处理程序中收到了一些“一般”错误。异常消息是:
从客户端检测到有潜在危险的 Request.Form 值
有很多方法可以触发它;只有一个例子是调用例如,
http:/www.mywebsite.com/http:/www.mywebsite.com/
我只想为这种异常创建一个“过滤器”,并相应地重定向或管理请求。我不想禁用它,只是为了管理它。我也不希望它属于通用的protected void Application_Error()
处理程序——或者,至少,我想在该方法内部管理它,这样它就不会被例如处理。我的日志记录。
我该如何管理?
【问题讨论】:
对此的正确响应是实际修复它并将端点标记为安全,以免出现错误。该错误是由 Microsoft 添加的,因为默认情况下,许多网站都被编写为具有类似注入的攻击。他们采取了比抱歉更安全的方法,默认情况下不允许使用看起来像 html 标记的表单数据的请求。对此的正确回应是检查您的代码,确保您在任何时候都没有将其直接呈现为 HTML 以触发此类攻击,然后告诉 ASP.NET MVC 您的端点是安全的。 错误消息,尽管它是针对传入的请求而编写的,但基本上表明您的应用程序不能保证以安全的方式编写。你不应该保留这个错误并以任何方式处理它,相反你应该确保你的应用程序可以处理表单数据,即使是看起来像 HTML 标记的东西,然后告诉 ASP.NET MVC 它是安全的。 @LasseV.Karlsen 我想避免它落入一般受保护的 void Application_Error() 中,我还有一些其他日志/东西。我需要以某种方式过滤它。你了解我的需要吗? 是的,您应该修复您的控制器和端点,使它们不会受到此类数据的攻击,然后将它们标记为安全,然后整个错误情况就会消失。你明白我在说什么吗? @LasseV.Karlsen 我怎样才能教 MVC http:/www.mywebsite.com/http:/www.mywebsite.com/ 是正确的 url? :O 【参考方案1】:听起来您已经配置了Application_Error()
事件处理程序,但不希望您的标准日志记录包含此类错误,大概是因为它使您的日志杂乱无章,其中包含您不打算进一步调查的异常。
背景
此错误是supposed to be,由HttpRequestValidationException
表示。如果这里是这种情况,当然,这将是一个微不足道的问题。然而,根据您提供的测试用例,您实际上得到了更通用的HttpException
。
作为 you noted in the comments,这是由于 .NET Framework 在评估 RequestValidator
之前对 URL early in the request pipeline 中的字符进行了验证。这可能是导致HttpRequestValidationException
没有被抛出的一个因素,否则如果RequestValidator
的IsValidRequestString()
方法返回false
就会发生这种情况。
解决方法
不幸的是,由于HttpException
类用于各种错误,这使得它难以处理。幸运的是,as you also discovered,您可以通过禁用web.config
中的requestPathInvalidCharacters
并配置自定义RequestValidator
来将此验证推送到RequestValidator
:
<configuration>
<system.web>
<compilation targetFramework="4.6.1" />
<httpRuntime
targetFramework="4.6.1"
requestValidationType="CustomRequestValidator"
requestPathInvalidCharacters=""
/>
</system.web>
</configuration>
注意:
requestValidationType
需要以其命名空间为前缀,假设它不在项目的根命名空间中。
requestPathInvalidCharacters
的默认值为<,>,*,%,&,:,\,?
,因此您现在需要在您的CustomRequestValidator
中重现该验证:
public class CustomRequestValidator : RequestValidator
private static readonly char[] requestPathInvalidCharacters = new [] '<', '>', '*', '%', '&', ':', '\\' ;
protected override bool IsValidRequestString(
HttpContext context,
string value,
RequestValidationSource requestValidationSource,
string collectionKey,
out int validationFailureIndex
)
if (requestValidationSource is RequestValidationSource.PathInfo || requestValidationSource is RequestValidationSource.Path)
var errorIndex = value.IndexOfAny(requestPathInvalidCharacters);
if (errorIndex >= 0)
validationFailureIndex = errorIndex;
return false;
return base.IsValidRequestString(
context,
value,
requestValidationSource,
collectionKey,
out validationFailureIndex
);
这首先重新创建路径验证(由value
参数表示),然后从基础RequestValidator
执行标准的开箱即用IsValidRequestString()
处理。现在这将抛出预期的HttpRequestValidationException
。
管理异常
在这一点上,如上所述,这现在变成了一个微不足道的问题。由于 RequestValidator
在解析 MVC 路由之前进行评估,因此您仍然不能在此处使用全局异常过滤器。但是,由于您已经设置了 Application_Error()
事件处理程序,因此您可以在您的 global.asax.cs
中通过以下方式管理它:
void Application_Error(object sender, EventArgs e)
Exception ex = Server.GetLastError();
if (ex is HttpRequestValidationException)
Response.Clear();
Response.StatusCode = 200;
// Manage request as you deem appropriate; e.g.,
Response.Redirect("~/Errors/RequestValidation/");
Response.End();
return;
// Your current logging logic
其他细节
对于几乎每个 ASP.NET 请求,RequestValidator
被调用至少两次——一次用于 pathinfo
(通常为空),一次用于path
(see requestValidationSource
)。每个QueryString
、Form
、Cookie
、Header
或绑定到路由的文件也将被验证。
Microsoft 尝试限制需要验证的请求。例如,他们不检查对静态文件的请求。此外,跳过未绑定到路由的参数。由于不能在路由参数键中使用具有潜在危险的字符,因此我们无需担心验证这些字符。
此外,正如您所指出的,对于无效的路径字符,也无需验证参数 values(例如 cookie 值)。集合值仍将通过基本 IsValidRequestString()
逻辑评估是否存在 其他 潜在危险字符串(例如 <script
)。
【讨论】:
这个怎么样? owasp.org/www-community/ASP-NET_Request_Validation @markzzz:我玩弄了覆盖RequestValidator
。我遇到的挑战是例外情况,例如~/http:/
或 ~/<
被抛出之前任何自定义请求验证器(或异常过滤器)被评估,因此直接转到您的 Application_Error()
处理程序。我怀疑这确实是这里的核心问题。我不确定这些正在评估中的何处,但它们似乎处于相对较低的水平。不幸的是,这让我回到了上面的答案。
如果你在web.config
上设置<httpRuntime targetFramework="4.6.1" requestPathInvalidCharacters=""/>
,它会在Application_Error()
之前调用。然后,在内部,您可以管理它们,将“原始”模式指定为匹配点。这些应该是 .NET 检查的字符:docs.microsoft.com/en-us/dotnet/api/…(您可以在完成自定义验证后设置)。你怎么看?
@markzzz:这是一个聪明的解决方法!我喜欢这个,因为它通过RequestValidator
统一了所有请求验证,允许您简单地处理标准HttpRequestValidationException
。 RequestValidator
仍然在 MVC 全局异常过滤器之前调用,但这很容易通过 Application_Error()
进行管理。这可能会通过将低级别验证推到管道中而增加一些开销,但这可能是可靠控制此错误的可接受折衷。我已经用经过测试的代码更新了我的答案——不过,在这一点上,功劳应该归你所有。
并非如此。如果现在用不需要的字符过滤“所有数据”,甚至是 cookie。我只需要过滤网址...该死的,这很成问题:(以上是关于如何处理“从客户端检测到潜在危险的 Request.Form 值”?的主要内容,如果未能解决你的问题,请参考以下文章
从客户端检测到潜在危险的 Request.Path 值 (&)
当 GoogleBot 访问时,“从客户端检测到潜在危险的 Request.Path 值”,但不是通过直接链接
将 html 标记从 jquery 发布调用发送到 asp.net 页面时,从客户端检测到潜在危险的 Request.QueryString 值