安全地在Python中评估字符串以调用hashlib

3 投票
4 回答
1421 浏览
提问于 2025-04-16 06:56

我想让大家可以提供一个哈希函数的名字,用来给某个对象做数字指纹识别:

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换成一个允许的算法的元组。)

撰写回答