Safely evaluate string in Python to call hashlib
I would like to allow people to provide the name of a hash function as a means of digitally fingerprinting some object:
def create_ref(obj, hashfn='sha256'):
"""
Returns a tuple of hexdigest and the method used to generate
the digest.
>>> create_ref({}, 'sha1')
('bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f', 'sha1')
>>> create_ref({}, 'md5')
('99914b93开发者_开发问答2bd37a50b983c5e7c90ae93b', 'md5')
"""
return (eval('hashlib.%s' % hashfn)(unicode(obj)).hexdigest(), hashfn)
Is hard coding hashlib
sufficently robust to prevent abuse of eval
?
No.
If you apply some of the SQL Injection attack concepts, it would be conceviable for the user to supply something like this:
"sha1(...); some_evil_code(); hashlib.sha1"
Which would totally blow the "security" away by ending up like this:
"hashlib." + "sha1(...); some_evil_code(); hashlib.sha1" + "(your-original-code)"
Which would result in 3 statements being run (a fine one, and evil one, and a fine one).
(even if the above code has holes in it, the concept could still be exploited)
Instead, use the dynamic power of python to make this work!
TYPES = ('sha256', 'sha1', 'md5', ...)
def create_ref(obj, hashfn='sha256'):
if hashfn not in TYPES:
raise ValueError("bad type")
# look up the actual method
fun = getattr(hashlib, hashfn)
# and call it on `obj`
fun(...)
Food for thought!
instead of eval, try this code:
def create_ref(obj, hashfn='sha256'):
"""
Returns a tuple of hexdigest and the method used to generate
the digest.
>>> create_ref({}, 'sha1')
('bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f', 'sha1')
>>> create_ref({}, 'md5')
('99914b932bd37a50b983c5e7c90ae93b', 'md5')
"""
allowed = hashlib.algorithms
if hashfn in allowed:
return (getattr(hashlib,hashfn)(unicode(obj)).hexdigest(), hashfn)
else:
raise NameError('Not a valid algorithm')
This will guarantee that the algorithm provided is a valid algorithm. (Note that hashlib.algorithms is new in 2.7, so if you use an older version, replace hashlib.algorithms with a tuple of allowed algorithms.
import hashlib
...
return (getattr(hashlib, hashfn)(unicode(obj)).hexdigest(), hashfn)
i think like this is more safely than using eval()
TYPES = {'sha256':hashlib.sha256 , 'sha1': hashlib.sha1, 'md5': hashlib.md5, ...}
def create_ref(obj, hashfn='sha256'):
#var 1 - use sha256 as default on invalid hashfun
#func=TYPES.get(hashfn, hashlib.sha256)
#var 2 raise error on invalid hashfun
if TYPES.has_key(hashfn):
func=TYPES[hashfn]
else:
raise NameError('Not a valid algorithm')
return (func(unicode(obj)).hexdigest(), hashfn)
精彩评论