home/blog/xxe


XXE injection (Cisco CTF)

2019-09-30

I scored a total of 3000 points out of 4100 in the Cisco SecCon CTF 2019. There were a lot of interesting problems. Here, I am going to write about a web challenge called Autograph. I still haven't figured out whether the statement had something to do with actual challenge or not. Moving on...

The first thing we see on the website is a registration form. There is a script in the source code to package all the information and send it as XML. There is also a comment <!-- EVERYONE EXCEPT "ADMIN" CAN REGISTER FOR THE EVENT !-->. After reading the comment, I tried putting in the name field's value as admin and realized that in order to get back the email's value reflected to the webpage, we require the name field to have the value admin. For ANY value of email it reflects back the email (saying that it already exists). I tried entering the form on the webpage with some random values and intercepted the request through Burp. After seeing the XML in the request body, I thought of trying out an XXE payload[1].

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY>
  <!ENTITY bar SYSTEM "file:///etc/passwd">
]>
<root>
	<name>admin</name>
	<email>&bar;</email>
</root>

The payload worked, as the /etc/passwd contents were returned.

Now we can browse around the server and see what all things there are. After scratching my head for a while, I remembered that the XML data is being submitted to process.php (the same file the XML data is posted to).

I thought of viewing this file on the server but when I tried to view it, I got the result of the php file executing and not the actual source code. In order to see the source code of the file, I used php://filter[2] to convert it into base64 and then got the contents reflected into the response.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY>
  <!ENTITY bar SYSTEM "php://filter/convert.base64-encode/resource=process.php">
]>
<root>
	<name>admin</name>
	<email>&bar;</email>
</root>

After getting the base64 encoded string, I decoded it and saw the contents of the process.php file. The first line contained an include to another file. Using the same technique as before, I got the source of the newly found file. This file had the flag.

SecConCTF{HEY_I_THOUGHT_XML_WAS_SAFE:(}

References - 2

[1] Portswigger - XXE injection
[2] PayloadAllTheThings - PHP Wrapper