CSAW CTF Qualifiers 2019

come get me


This was a web challenge with a few pages. The “User” page displayed some user information:

Screenshot of User page, transcribed below

Name: Alice
Email: [email protected]
Group: CSAW2019
Intro: Alice is cool

Name: 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:

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.

Screenshot of Upload page, with a form to Upload New Users

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:

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.


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:

Converting to UTF-16 as before and uploading, we see:

Screenshot of User page displaying the flag after our uploaded exploit

There’s our flag, amidst all the other screaming A’s:


(note: the commenting setup here is experimental and I may not check my comments often; if you want to tell me something instead of the world, email me!)