Note
web
python
request-smuggling
http-desync
gunicorn
hypercorn
transfer-encoding
Desync a frontend and a Python backend that disagree on TE/CL, whitespace, or line endings to inject a second request.
Request Smuggling against Hypercorn / Gunicorn
Different HTTP hops disagree about where one request ends and the next begins. If the frontend and the
Python backend parse Transfer-Encoding, Content-Length, whitespace, or line endings differently,
attacker-controlled bytes escape into the backend as a second request.
Why It Works
- The bug is architectural: a reverse proxy / WAF / frontend making one parsing choice and the backend making another is enough.
- Known weaknesses include Gunicorn TE handling, Hypercorn line-ending leniency, and latin1 header-name confusion.
Vulnerable Pattern
- Apache, Traefik, Nginx, or a custom frontend talking to Gunicorn/Hypercorn over keep-alive HTTP/1.1.
- Any chain where the proxy and backend differ on hop-by-hop header parsing.
Exploit Flow
- Identify the exact hop chain — smuggling only matters if the backend sees bytes the proxy didn't model as a second request.
- Test TE.CL and CL.TE with raw requests before exotic variants.
- If classic probes fail, mutate
Transfer-Encodingsyntax: commas, tabs, duplicate headers, NBSP, odd line endings. - Once desync is confirmed, target internal-only routes, alternate vhosts, cache poisoning, or request-body confusion on admin endpoints.
Variations
Transfer-Encoding: chunked,gzip,TE:\tchunked, header-name NBSP, mixed\nvs\r\n, or HTTP/0.9 / response-splitting style backend confusion.- If the backend route isn't directly useful, aim for an internal upload, debug route, or secondary proxy endpoint.
Common Blockers
- Connection reuse disabled between hops, frontend normalization that fixes the backend bug, or no useful internal target even after desync.
- A backend 404 isn't enough — confirm the smuggled request actually reached the route you care about.
PoC Sketch
Transfer-Encoding: chunked
Content-Length: 4
0\r\n\r\nGET /internal/upload HTTP/1.1\r\nHost: backend\r\n\r\n
# then mutate TE to values like chunked,gzip or TE:\tchunked
Good Situations To Use It
- A multi-hop HTTP/1.1 chain with keep-alive between proxy and a Python app server.
- You have a known internal-only route worth reaching.
- Classic TE/CL probes already show parsing differences.
Sources
0xFUN2026/web/skyport_opsfcsc2026/web/bubulle_corp_2sthack2026/web/magic_claw_2ehaxctf2026/web/megacorp(lead)ehaxctf2026/web/modernshop(lead)