如何在ASP.NET WebForms中禁用HTTP方法隧道及实现疑问
问题背景
在MicroFocus Web安全扫描中检测到高危漏洞**"Often Misused: HTTP Method Override"**,该漏洞核心风险为:攻击者可通过GET、POST等可信HTTP方法,附加X-HTTP-Method、XHTTP-Method-Override、X-Method-Override请求头或_method查询参数,传递PUT、DELETE等受限方法,让应用按请求头中的方法解析请求,进而绕过权限控制或执行未授权操作。
已有开发者针对Fortify WebInspect的同类问题,实现了Java Servlet过滤器,检测到可疑请求头/参数时返回405状态码,代码如下:
@Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest hsReq = (HttpServletRequest) req; HttpServletResponse hsRes = (HttpServletResponse) res; hsRes.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); hsRes.setHeader("Pragma", "no-cache"); hsRes.setDateHeader("Expires", 0); hsRes.setHeader("X-XSS-Protection", "1; mode=block"); hsRes.addHeader("X-Content-Type-Options", "nosniff"); hsRes.setHeader("Content-Security-Policy", "frame-ancestors 'none'; default-src *; style-src 'self' http://* 'unsafe-inline'; script-src 'self' http://* 'unsafe-inline' 'unsafe-eval'"); hsRes.setHeader("X-FRAME-OPTIONS", "DENY"); hsRes.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains;"); // 修复"Often Misused: HTTP Method Override"漏洞 hsRes.setHeader("Access-Control-Allow-Methods", "GET, POST"); String methodParam = hsReq.getParameter("_method"); if (methodParam != null){ LOG.error("\n Bad actor is attempting to use HTTP Method Tunneling. \n"); hsRes.reset(); hsRes.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED); return; } String xhmHeader = hsReq.getHeader("x-http-method"); String xhmoHeader = hsReq.getHeader("x-http-method-override"); String xmoHeader = hsReq.getHeader("x-method-override"); if ((xhmHeader != null) || (xhmoHeader != null) || (xmoHeader != null)){ LOG.error("\n Bad actor is attempting to use HTTP Method Tunneling. \n"); hsRes.reset(); hsRes.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED); return; } chain.doFilter(req, res); }
ASP.NET WebForms中的实现方案
1. 自定义HttpModule的放置与调用
ASP.NET WebForms无直接对应Servlet Filter的组件,可通过HttpModule实现全局请求拦截,步骤如下:
步骤1:创建HttpModule类
在项目中新建类(如HttpMethodOverrideModule.cs),实现IHttpModule接口,移植核心逻辑:
using System; using System.Web; using System.Diagnostics; namespace YourNamespace { public class HttpMethodOverrideModule : IHttpModule { public void Init(HttpApplication context) { context.BeginRequest += OnBeginRequest; } private void OnBeginRequest(object sender, EventArgs e) { HttpApplication app = (HttpApplication)sender; HttpRequest request = app.Context.Request; HttpResponse response = app.Context.Response; // 设置安全响应头(与Java代码对应,可按需调整) response.Headers["Cache-Control"] = "no-cache, no-store, must-revalidate"; response.Headers["Pragma"] = "no-cache"; response.Expires = 0; response.Headers["X-XSS-Protection"] = "1; mode=block"; response.Headers["X-Content-Type-Options"] = "nosniff"; response.Headers["Content-Security-Policy"] = "frame-ancestors 'none'; default-src *; style-src 'self' http://* 'unsafe-inline'; script-src 'self' http://* 'unsafe-inline' 'unsafe-eval'"; response.Headers["X-FRAME-OPTIONS"] = "DENY"; response.Headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains;"; response.Headers["Access-Control-Allow-Methods"] = "GET, POST"; // 检测_method参数 string methodParam = request.QueryString["_method"]; if (!string.IsNullOrEmpty(methodParam)) { EventLog.WriteEntry("Application", "HTTP Method Tunneling attempt via _method parameter.", EventLogEntryType.Error); response.Clear(); response.StatusCode = 405; response.End(); return; } // 检测可疑请求头 string xhmHeader = request.Headers["x-http-method"]; string xhmoHeader = request.Headers["x-http-method-override"]; string xmoHeader = request.Headers["x-method-override"]; if (!string.IsNullOrEmpty(xhmHeader) || !string.IsNullOrEmpty(xhmoHeader) || !string.IsNullOrEmpty(xmoHeader)) { EventLog.WriteEntry("Application", "HTTP Method Tunneling attempt via request headers.", EventLogEntryType.Error); response.Clear(); response.StatusCode = 405; response.End(); return; } } public void Dispose() { // 按需清理资源 } } }
步骤2:注册HttpModule
在Web.config中根据.NET运行模式配置:
集成模式(.NET Framework 4.0+):
<system.webServer> <modules> <add name="HttpMethodOverrideModule" type="YourNamespace.HttpMethodOverrideModule" /> </modules> </system.webServer>
经典模式:
<system.web> <httpModules> <add name="HttpMethodOverrideModule" type="YourNamespace.HttpMethodOverrideModule" /> </httpModules> </system.web>
2. 更简洁的解决方案:Global.asax直接处理
无需创建独立模块,直接在Global.asax的Application_BeginRequest事件中编写逻辑:
protected void Application_BeginRequest(object sender, EventArgs e) { HttpRequest request = Context.Request; HttpResponse response = Context.Response; // 检测_method参数与可疑请求头 bool hasMethodOverride = !string.IsNullOrEmpty(request.QueryString["_method"]) || !string.IsNullOrEmpty(request.Headers["x-http-method"]) || !string.IsNullOrEmpty(request.Headers["x-http-method-override"]) || !string.IsNullOrEmpty(request.Headers["x-method-override"]); if (hasMethodOverride) { EventLog.WriteEntry("Application", "HTTP Method Override attempt detected.", EventLogEntryType.Error); response.Clear(); response.StatusCode = 405; response.End(); return; } // 可选:设置允许的HTTP方法头 response.Headers["Access-Control-Allow-Methods"] = "GET, POST"; }
优势:
- 无需额外类与配置,代码轻量化
- 全局入口直接处理,逻辑直观易维护
内容的提问来源于stack exchange,提问作者Jim Beaumont
相关产品推荐
相关产品推荐

