Published on

Bypassing WAF Method Blocks with X-HTTP-Method-Override

Authors

In this post I want to cover a simple trick that is still surprisingly effective during web testing: abusing x-http-method-override to bypass method restrictions.

If you are sending GET or POST and the WAF keeps throwing back 403, this is one of those things that is always worth trying.

The Problem

A lot of WAF policies are written around direct method checks. For example:

  • Block suspicious GET requests to sensitive routes
  • Block POST requests that look like automation or payload delivery
  • Allow OPTIONS for CORS preflight handling

At a high level this sounds fine, but the gap appears when the edge layer and backend do not agree on what the real HTTP method is.

Some frameworks and proxies support method tunneling via headers like:

  • X-HTTP-Method-Override
  • X-Method-Override
  • X-HTTP-Method

So if the WAF evaluates OPTIONS but the application later treats the request as GET or POST, you can end up with a clean bypass.

The Bypass

The idea is straightforward:

  1. Send OPTIONS as the real HTTP method
  2. Add x-http-method-override: GET or x-http-method-override: POST
  3. Keep the rest of your request as normal

Example for forcing a GET:

curl -i -X OPTIONS "https://target.com/protected/resource?id=123" \
  -H "x-http-method-override: GET" \
  -H "user-agent: Mozilla/5.0"

Example for forcing a POST:

curl -i -X OPTIONS "https://target.com/api/update-profile" \
  -H "x-http-method-override: POST" \
  -H "content-type: application/json" \
  -d '{"displayName":"test"}'

If normal GET/POST calls are blocked with 403 but these go through, you've likely found a method handling mismatch between layers.

Why This Works

Most of the time this comes down to inconsistent request normalization:

  • The WAF enforces policy on the network-level method (OPTIONS)
  • The backend or middleware honors override headers and rewrites method semantics
  • Security controls are not re-applied after the method is overridden

This is basically a trust boundary issue. One layer trusts the raw method while another layer trusts a user-supplied header.

How To Stop This Attack

From the defensive side, this is very fixable if you standardize method handling end-to-end.

  1. Disable method override headers unless absolutely required.

If your app does not need tunneling, reject these headers entirely:

  • X-HTTP-Method-Override
  • X-Method-Override
  • X-HTTP-Method
  1. Enforce method allowlists at every layer.

Do not rely only on the WAF. Apply method restrictions at:

  • WAF / CDN edge
  • Reverse proxy or API gateway
  • Application routing/middleware
  1. Normalize and validate before authorization logic.

If your platform supports overrides for legacy reasons, normalize once, then perform all authorization and security checks on the final effective method.

  1. Log and alert on method override usage.

In most modern apps, override headers are rare. Treat unexpected usage as suspicious and alert on:

  • OPTIONS with body content to non-CORS endpoints
  • Any request carrying override headers to sensitive routes
  • Spikes in 403-to-200 patterns after method changes
  1. Add security tests for verb tunneling.

Include negative tests in CI/CD that verify blocked GET/POST endpoints cannot be reached by:

  • OPTIONS + X-HTTP-Method-Override
  • POST + X-HTTP-Method-Override: DELETE
  • Alternative override header names and casing variants

Conclusion

In summary, x-http-method-override bypasses are a great reminder that security controls fail when layers disagree on request semantics.

If a WAF is only looking at the transport method while the backend trusts override headers, you've got a crack in the pipeline.

This highlighted the importance of:

  • Consistent method parsing across edge, proxy, and app layers
  • Failing closed on unexpected override headers
  • Logging and testing for method tunneling abuse as part of normal security validation