Security/Safety question re: eval() and dicts

andy andy at eastonwest.co.uk
Sun Jan 26 00:59:16 CET 2003


This is probably one for the Language Lawyers and Zen Pythonistas out there...

I'm still working (as time permits) on the 'repository' module I mentioned a 
few weeks ago.  

I've renamed it 'chalkboard' to better convey its purpose, and subtitled it 
'lightweight remote shared dictionary' to further underline its 
insignificance as an industrial-strength mission-critical utility module :-)  

Still, I don't want the security side to be totally crap, so I thought I'd 
better try to plug it's most glaring hole of all...

The prototype server (and client for that matter) receive requests, via a 
socket connection, as a string value which is supposed to be formatted as a 
Python dictionary, eg.

client sends: 
    {"request":"query","keys":{"abc":0,"def":0}}

server responds: 
    {"request":"query","keys":{"abc":123,"def":456}}

Currently, this is decoded by using 

    dict=eval(request) 
    if dict.has_key("request"):
        req=dict["request"]
        if req="query":
            # process query
        elif req="set":
            # set a key
    else:
        response='{"error":"malformed request"}'

So, I guess this is akin to juggling with fireworks in a welding shop...

For a start, one could repeatedly send:
    {"foad":"!" * 1024 * 1024  * 100}

Not very imaginative, I suppose, but , it crashes Python on my Linux box.

As a 'first-line' of defense, I'm proposing to 'vet' the request string before 
submitting it to eval() - my question is, can I simply perform a few simple 
tests, to verify that the string truly is a dictionary? What I have so far 
is:
    1) Verify it starts and ends with "{" and "}"
    2) Ensure that it is simply a sequence conforming to:
        "keyname" : value,
    3) Ensure that nothing after a colon constitutes a function call, 
        expression or list comprehension, ie:
        "keyname" : ident(...),
        "keyname" : [expr for var in list],
        "keyname" : "string" * number,

Is there anything else I should be aware of?  Any skeletons or spectres in 
Python syntax that could allow this approach to be exploited?  Remember that 
this is not intended to be an impenetrable fortress, with the self-healing 
capabilities of a federation startship... :-)  ... that can come later!

regards, 
-andyj





More information about the Python-list mailing list