I'm failing a MicroFocus web security scan with a "High" vulnerability - "Often Misused: HTTP Method Override".
"The attack request uses a trusted HTTP verb such as GET or POST, but adds request headers such as X-HTTP-Method, XHTTP-Method-Override, X-Method-Override, or a query parameter such as _method to provide a restricted verb such as PUT or DELETE. Such a request is interpreted by the target application using the verb in the request header instead of the actual HTTP verb."
Someone has already asked this question and someone responded as such:
"It looks like you're getting the issue "Often Misused: HTTP Method Override" reported by Fortify's WebInspect scanner. To resolve this for my team I implemented a filter that listens for our bad headers (x-http-method, x-http-method-override, x-method-override), sets status to 405 and breaks if they are found. See code below. I know this is not the most graceful solution, but it is the only one I found that satisfies the scan (throwing an error and booting the user did not satisfy)."
Here is their coded "filter":
@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;");
// This resolves "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);
}
My question is, where would someone place this code in an ASP.NET WebForms application and where would you call it from? Is there a simpler and more straightforward solution?
Building on Faust's answer, I implemented it this way. It is slightly shorter. I fixed the spelling. I don't check the value of the bad header, just the presence of the bad header is a fail. I chose to return 400.6 (bad request body) instead of 404.6 (verb denied) since I am denying the way you are asking to run the verb, not denying the verb itself. I am not sure which is better. 404 is just so common I preferred to to see 400 bad request.
I also used almost the same web.config piece. I added a clear tag suggested by some other references.