开发者

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜