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

Victor Stinner victor.stinner at haypocalc.com
Tue Feb 24 01:43:11 CET 2009

Le Tuesday 24 February 2009 01:31:55 Victor Stinner, vous avez écrit :
> (...)
> But how can we get the closure if b.func_closure doesn't exist? Oh, wait!
> What's this: b.__getattribute__...
> -------------------------------------
> secret = get_cell_value(b.__getattribute__('func_closure')[0])
> -------------------------------------
> (...)

Before this exploit, I tried to rewrite get_cell_value() to avoid reading 
func_xxx ... but it does work, I always need the closure data to get the 
secret. Anyway, I think that creating executing arbitrary Python bytecode 
have to be blocked!

  compile() have to be removed from __builtins__

Extract of my try to rewrite get_cell_value():
# get code class
c = compile('1', '<string>', 'eval')
code = c.__class__

# get function class
def func():
function = type(func)

#  code(argcount, nlocals, stacksize, flags, codestring, constants, names,
#        varnames, filename, name, firstlineno, lnotab, freevars, cellvars)
func_code=code(0, 0, 1, 19, '\x88\x00\x00S', (None,), tuple(),
         tuple(), '<string>', 'hack', 3, '\x00\x01', ('fileobj',), tuple())

closure = b.func_closure   # FIXME: Get b closure!?
newread = function(func_code, globals(), func_code.co_name, None, closure)
fileobj = newread()

I'm able to get the code class and so create arbitrary code object, that's 
bad! If the user is unable to create a code object (no more compile()) or to 
get the code of a function, it's fine.

Note: The byteocode is the bytecode of b() in the following code:

def a():
  secret = 42
  def b():
     return secret
  return b()

Victor Stinner aka haypo

More information about the Python-Dev mailing list