[Python-Dev] Challenge: Please break this! [Now with blog post]

tav tav at espians.com
Tue Feb 24 08:07:17 CET 2009


  guido> I can access the various class and metaclass objects
  guido> easily [snip]

It would've been possible to replace __call__ on the metaclass --
which, though not a security leak by itself, could've been abused for
some fun.

I've inlined the __metaclass__ to prevent fun of this kind.

But the really tricky one so far is this hardcore hack that Paul
Cannon emailed in:

>>> from safelite import FileReader
>>> __builtins__.TypeError = type(lambda: 0)(type(compile('1', 'b', 'eval'))(2, 2, 4, 67, 'y\x08\x00t\x00\x00\x01Wn\x09\x00\x01\x01a\x00\x00n\x01\x00X|\x01\x00|\x00\x00\x83\x01\x00S', (None,), ('stuff',), ('g', 'x'), 'q', 'f', 1, ''), globals(), None, (TypeError,))
>>> try:
...   FileReader('foo', 2)
... except:
...   pass
...
>>> stuff.tb_frame.f_back.f_locals['open_file']('w00t', 'w').write('yaymore\n')

He explains it in detail here:
http://thepaulprog.blogspot.com/2009/02/safelite-exploit.html

It's very cool!

He uses the ``compile`` builtin to get hold of the CodeType and then
uses that to construct a nifty function with custom bytecode. Turns
out that with the bytecode one can grab traceback objects off of the
stack!!

And, from there, it's just a mere attribute access away to get hold of
traceback.tb_frame!

Paul, wisely, outlines the two possible options to remedy this:

1. Remove ``compile`` from the safe builtins
2. Take out ``tb_frame``

If compile is not present and given that func_code and gi_code are not
present -- are there other ways of getting at the CodeType? If there
aren't then getting rid of compile gives us an easy win.

If getting rid of tb_frame is the approach -- then you were right
Guido -- there are more variables which need to be restricted! But,
this just makes the patch into 7 lines of code instead of 6, so I'm
still happy =)

The only thing I can't figure out is how to get rid of the attribute
using ctypes for the safelite challenge as calling
dictionary_of(TracebackType) in safelite.py presents a very minimal
{'__doc__': None}

Also, the comments in Lib/types.py states:

    # In the restricted environment, exc_info returns (None, None,
    # None) Then, tb.tb_frame gives an attribute error

I can't seem to find the place in the Python source where exc_info()
behaves differently under restricted mode...

Thoughts on which of the two options is better would be very appreciated!

And thanks for the ongoing hacks guys -- this is turning out great!!

-- 
love, tav

plex:espians/tav | tav at espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian


More information about the Python-Dev mailing list