Tags: xxe waf-bypass 

Rating: 5.0

# Challenge Name: Unagi
Score: 200

Vulnerability: External XML Entity (XXE)

Solution: Bypass character encoding

Link: http://web.chal.csaw.io:1003

**Part 0x01 - Information Gathering**

There are three interesting pages on the website: [user](http://web.chal.csaw.io:1003/user.php), [upload](http://web.chal.csaw.io:1003/upload.php), and [about](http://web.chal.csaw.io:1003/about.php). This site is written using PHP based on the file extensions of the pages.

Displayed information of users on `user.php` page are `name`, `email`, `group`, and `intro`. In `upload.php` page, there's a format sample in XML. (http://web.chal.csaw.io:1003/sample.xml)
<name> Bob</name>
About.php page gives us a hint that the flag is located at `/flag.txt`.

**Part 0x02 - Vulnerability Exploitation**

We can perform an External XML Entity (XXE) attack on this challenge.
Adding the following payload `]>` throws a WAF error message.
So to solve this, we have to look for WAF bypass to exploit the vulnerability.

Searching on Google gives us this article: https://www.phdays.com/en/press/news/phdays-vi-waf-bypass-contest/. Check out #3 for XXE WAF Bypass.

The author found out that if we converted the character encoding of UTF-8 to UTF-16 Big Endian, we could easily bypass the WAF.
> encoded the body in UTF-16 Big Endian via the command cat x.xml | iconv -f UTF-8 -t UTF-16BE > x16.xml

Using the sample.xml given by the challenge author, we will convert the character encoding of the file to UTF-16BE.


After uploading the XML file, we managed to retrieve the `passwd` file from the internal server. However, it only prints 20 characters.

I tried adding the variable to Name and Email but the same result. Fortunately, I remembered that there's another field named `intro` in the user page. I then added it to the XML file and converted the character encoding again.


Uploading it to the challenge website will give us the content of the `passwd` file.


But that doesn't mean we can quickly get the `flag` located at `/flag.txt`. To get the flag, I have to use the `php://filter` wrapper.

Final Payload would be

Uploading it will print a BASE64 cipher.


Decoding it to text will give us the flag.


Thanks for reading.

Original writeup (https://github.com/ajdumanhug/ctf/blob/master/web/xxe/csaw-unagi-web-200.md).