Python中白名单能否保障exec()与eval()安全?如何提升安全性?
白名单能否让exec()/eval()安全?还有哪些优化空间?
老兄,你的这个问题问到点子上了——很多人觉得靠白名单约束exec/eval的调用范围就万事大吉,但实际情况要复杂不少。先给你个明确结论:白名单能显著提升安全性,但没法做到100%绝对安全,而且如果你的白名单校验方式不对,很可能形同虚设。下面我拆解下核心风险,再给你几个落地的安全优化方案:
为什么白名单不能完全“拯救”exec()/eval()?
哪怕你做了白名单校验,这些风险依然可能存在:
- 字符串匹配的白名单容易被绕过:如果你的校验只是简单检查用户传入的函数名字符串是否在白名单里,攻击者可以构造带有属性链的恶意字符串,比如
"safe_func.__globals__['os'].system('rm -rf /')"——表面上是白名单里的safe_func,实际执行的是删除系统文件的危险命令。 - 函数本身的安全隐患:就算函数在白名单里,如果这个函数本身设计有漏洞(比如接受危险参数、能访问敏感资源),用户传入的字典参数可能被用来触发风险。比如白名单里有个处理文件路径的函数,用户传入恶意路径片段可能导致路径遍历攻击。
- 白名单维护漏洞:如果管理员误把危险函数加入白名单,或者清单文件权限配置不当被篡改,整个防护体系直接失效。
怎么进一步提升安全性?
这里给你几个优先级从高到低的方案,越靠前越安全:
1. 彻底抛弃exec()/eval(),直接用函数对象映射
这是最安全的方案,从根源上避免了代码注入风险。具体做法是:
- 后端预加载所有允许的函数,维护一个函数别名→函数对象的字典;
- 用户请求中只需要指定函数别名,系统直接从字典中取出函数对象调用,完全不用解析字符串。
示例代码:
# 预加载安全函数,由管理员维护 allowed_functions = { "process_user_data": backend_workflow_lib.process_user_data, "validate_input": backend_workflow_lib.validate_input } # 处理用户请求 user_request = request.get_json() func_name = user_request.get("function_name") user_dict = user_request.get("data") if func_name not in allowed_functions: return {"error": "Function not allowed"}, 403 # 直接调用函数,无exec/eval风险 result = allowed_functions[func_name](user_dict)
2. 如果必须用exec()/eval(),严格限制执行环境
如果因为特殊需求不得不保留exec/eval,一定要做这几件事:
- 禁用内置函数:给exec/eval传入一个干净的全局命名空间,只包含白名单函数,并且把
__builtins__设为None,避免攻击者调用内置的危险函数(比如eval、exec、open); - 校验函数名格式:确保用户传入的函数名是单纯的标识符(不含
.、__等特殊字符),防止属性链绕过; - 隔离局部变量:用局部命名空间传递用户参数,避免污染全局环境。
示例代码:
import re # 仅包含白名单函数的干净全局空间 safe_globals = { "process_user_data": backend_workflow_lib.process_user_data, "__builtins__": None } user_func_name = user_request.get("function_name") # 校验函数名格式:只能是字母、数字、下划线 if not re.match(r'^[a-zA-Z0-9_]+$', user_func_name): return {"error": "Invalid function name"}, 403 if user_func_name not in safe_globals: return {"error": "Function not allowed"}, 403 # 用局部空间传递参数,执行函数 local_vars = {"user_dict": user_dict, "result": None} exec(f"result = {user_func_name}(user_dict)", safe_globals, local_vars) result = local_vars.get("result")
3. 严格校验用户传入的字典参数
不管用不用exec/eval,都要对用户传入的JSON字典做严格校验:
- 校验字段的存在性、类型、取值范围;
- 对敏感字段(比如路径、命令参数)做规范化和过滤,比如路径要做绝对路径转换并限制在指定目录内;
- 避免直接把用户参数传递给有风险的函数参数(比如
subprocess的shell=True参数绝对不能用用户输入)。
4. 遵循最小权限原则
执行函数的进程/线程要用最小权限运行:
- 不要用root或管理员权限启动应用;
- 限制应用的文件系统访问范围(比如用chroot、容器化);
- 避免应用能访问敏感配置(比如数据库密码、API密钥),必要时用环境变量或加密存储。
5. 定期审计与维护
- 定期检查白名单函数的实现,及时移除不再需要的函数;
- 关注后端工作流库的安全更新,避免使用有已知漏洞的函数;
- 审计应用的访问日志,排查异常请求。
内容的提问来源于stack exchange,提问作者Freefall
相关产品推荐
相关产品推荐

