安全地在Python中评估字符串以调用hashlib
我想让大家可以提供一个哈希函数的名字,用来给某个对象做数字指纹识别:
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')
"""
return (eval('hashlib.%s' % hashfn)(unicode(obj)).hexdigest(), hashfn)
直接写死hashlib
这样做,能不能有效防止eval
被滥用呢?
4 个回答
1
import hashlib
...
return (getattr(hashlib, hashfn)(unicode(obj)).hexdigest(), hashfn)
我觉得这样比用eval()要安全得多。
4
不。
如果你了解一些SQL注入攻击的概念,用户可能会输入类似这样的内容:
"sha1(...); some_evil_code(); hashlib.sha1"
这样做会完全破坏“安全性”,最终变成这样:
"hashlib." + "sha1(...); some_evil_code(); hashlib.sha1" + "(你的原始代码)"
这会导致执行三条语句(其中一条是正常的,一条是恶意的,还有一条是正常的)。
(即使上面的代码有漏洞,这个概念仍然可以被利用)
相反,利用Python的动态特性来实现这个功能吧!
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(...)
值得思考的内容!
3
不要使用eval,试试这个代码:
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')
这样可以确保你提供的算法是有效的。(注意,hashlib.algorithms是在2.7版本中新加的,如果你用的是旧版本,就把hashlib.algorithms换成一个允许的算法的元组。)