## Sunday, December 29, 2013

### 30C3 CTF - PyExec (sandbox 300)

TL;DR: # coding: unicode_escape

PyExec was a python-sandbox-escape type challenge on the recent 30C3 CTF. Basically you were allowed to execute filtered Python code server-side, where the filter was a mix of a blacklist and a whitelist. The solution turned out to be quite amusing :)

The code was fed to the server using a very simple web app that looked like this:

Since you were also given the source code of the server, you could peek at the filtering code, which worked like this:

• It blacklisted all interesting function names (strings search), like "open" or "eval".
• It allowed (whitelisted) only characters that matched this regular expression:
^[\r\na-z0-9#\t,+*/:%><= _\\\-]*$The regexp allows: • whitespaces • lower letters (only lower, no upper) • digits • and these special characters: # , + * / \ : % > < = _ - If the filter disliked something, the code was not executed. Codes that passed the filter were written into a temporary file and executed by an external Python process. The solution is obvious if you have played with Python source code charsets before - declare a coding using the # coding: name directive and encode your payload with it. At first we tried to go with utf-7, but since no upper characters are allowed, that turned out to be a no go. Finally we settled for a Python-specific codec called unicode_escape which allows the whole source code to look like inside-a-string escape sequences: # coding: unicode_escape \x41\x41\x41\x41 In the end we've encoded a Python reverse shell to this encoding and used it to find and read the flag: > nc -v -l 1234 Connection from 88.198.89.213 port 1234 [tcp/*] accepted /bin/sh: 0: can't access tty; job control turned off$ ls
flag.txt
static
webapp.py
$cat flag.txt 30C3_2a2766d9cf4a137d517a8227bd71d59d$

And that's it.