Python "sandbox" escape (last update: 2016-12-04, created: 2013-05-06) back to the list ↑
So as I've recently learnt Python "sandbox" (as in removing _builtins_, and similar tricks) doesn't work. And it seems this is sometimes useful since different projects tend to use a Python "sandbox" anyway. So I decided to put some links / notes here.
(btw, this is about Python 2.6/2.7, not 3.X)
# Trick 1
If __builtins__ are removed, and import doesn't work, you can use this:
The 49 there is warnings.catch_warnings in my case, however I recall on a different python version there was another warning-related class which has the same _module thing.
This basically solves the problem of missing import.
# See also
Basically any CTF writeup about python jail/sandbox escape.
The PlaidCTF 2014 had a _nightmare_ task where you could execute any code, but there was nothing in the environment except stdout.
It was solvable by accessing /proc/self/mem of the Python process and overwriting something. In our case we overwritten the fopen64 address in the .got/.plt with the address of system, and were able to run any command by just using type(stdout)("command").
https://docs.google.com/document/d/1pgl19sRdNGH1mYNdjoZSRtkAFTn0TQYR7bhUDw99sew/edit#bookmark=id.hub6v8dj4caa (by q3k and me)
On the 0x3004 CTF recently there was a different kind of task, which looked like this:
I played with the task quite a lot but in the end didn't manage to solve it. The organizers said there were two solutions, both really sweet:
*Solution 1*: max(open([list(vars())for(password)in]))
It basically creates a new local variable called "password" (it's the newly defined iterator in the for loop), and then uses the name of this variable (that's the list(vars()) - the number here might vary; on the CTF server it was 8) as the name to open the ./password file. The max() there is used to read the data from the file; list(open(...)) would work as well, but max is shorter.
Lesson: you actually could create new variables here
*Solution 2*: [chr(53)for(vars()[list(vars())])in]
This one works by replacing the LEN_PASS variable with 1 (this is done by using the the LEN_PASS variable (hint: reference) - that's the vars()[list(vars())] part - as a value-iterator for the  array; which basically means it sets it to 1) and then returning always a given character - in this case it was "5" (of course, you had to brute-force this character on the server).
Lesson: list-for can be used to set existing variables, even if they are access in a really strange way