September 17, 2017

CSAW CTF 2017 - Web 150 Write-Up [Shia Labeouf-off!]

It was about time for something a little bit different around here, so here's my write-up for the CSAW CTF 2017 -- Web 150 challenge titled Shia Labeouf-off! Hope it's as enjoyable to read as I enjoyed solving it.

From the start, we are given very little as many CTFs do. We're directed to a URL running a rather ridiculous webapp about the man, the myth, the legend... Shia Labeouf...

The Strategy

I clicked all the links and watched the traffic in Burp Suite to see if anything interesting was taking place. For the most part, everything was rather boring. I began fuzzing random input in the ad-lib generator when I stumbled upon the first clue, a Django debug page.

Based on the error, I figured we were dealing with SSTI (Server-Side Template Injection). I have read posts prior to this on Flask Jinja template injection, but I had never read anything about Django's template system being injectable. In fact, I was under the impression Django was pretty solid (as a web framework goes...).

After digging through this debug page, I noticed the load pools_extras statement on line 3 of the debug output. I had no idea what that line did, so I started digging into the Django docs. That digging led me to finding this Django doc:

Turns out you can define custom template tags in Django and then use them once you've loaded that specific module. The problem is that you need the source code from the custom template tag module to know what the name of the custom tags are.

The Solution

This led me down a horrible side-path that went absolutely nowhere. I tried finding a .git directory assuming there might be a git repository we needed to use to find something else. This was a complete waste of time, but it allowed me to accidentally find another Django error page which was helpful. The polls section of the web app numbers each poll. If you specify a poll number greater than 2, you get a very helpful error page.

Scrolling down this page, you eventually find an exception that occurs in which is the file we need to see the source code for. Django kindly allows you to expand the source code of the problematic code and now we have the info we need!

We can see there are a few custom template tags that are defined for us: getme, checknum, listme. Based on the Django docs earlier, these tags can be used in the ad-lib generator to potentially get us somewhere. The problem is that when you go back and re-read the docs, you can only apply a custom tag to a predefined Django Template Context variable. Again, I hit the wall... 

The example from the Django docs. Custom tags are applied to a predefined variable via the pipe character. Ughhhh...

I began pouring over the original Django error page again and found something rather odd. See if you can notice it as well.

Sorry to ruin the surprise if you didn't catch it, but what the actual hell is mrpoopy which is defined in the RequestContext object. Rick and Morty always seems to randomly appear lately... So, what the hell is inside this object?? Let's use one of those fancy custom template tags to find out, shall we?

The payload: {{ mrpoopy|listme }}

So, it appears there are a few attributes of mrpoopy and they are: Woohoo, __doc__, __flag__, __module__. I'm sure you can see where this is going at this point. We have the flag right in front of our faces! Sure enough, there's another custom tag to get an attribute, so let's see what happens...

The payload: {{ mrpoopy|getme:"__flag__" }}

And there you have it, SSTI of Custom Django Template Tags leads us to obtaining a flag. The hardest part of this one was figuring out the syntax for applying a custom tag. It's really quite odd.

Hope you enjoyed the play-by-play of solving Web 150 of CSAW 2017. I hope to do more of these as time permits!


The S3 Bucket Problem - The Latest Vuln to Become Popular

Yes, yes, I'm late to the party, I know. Poorly secured Amazon S3 buckets have been a thing for a while now, but recently there's...