0

0

如何使用Python发现不安全的eval()使用?

蓮花仙者

蓮花仙者

发布时间:2025-07-24 09:27:02

|

792人浏览过

|

来源于php中文网

原创

python中的eval()被视为不安全函数的核心原因在于其能够执行任意代码,导致严重的安全风险,尤其当输入来源不可信时。①攻击者可构造恶意输入,执行如文件操作、数据泄露等危险行为;②即使尝试通过限制globals和locals参数构建“沙箱”,也难以真正安全;③推荐使用ast.literal_eval()、json.loads()等替代方案;④通过ast静态分析可有效识别eval()调用并评估其风险等级;⑤运行时应严格验证输入、限制权限并避免eval()的使用。

如何使用Python发现不安全的eval()使用?

在Python项目中识别并处理不安全的eval()使用,核心在于理解其带来的巨大安全风险,并结合静态代码分析与必要的运行时考量。最直接有效的方法是利用Python内置的ast模块进行抽象语法树分析,辅以代码审查和对替代方案的深入理解。

如何使用Python发现不安全的eval()使用?

解决方案

要发现不安全的eval()使用,我们可以编写一个脚本来遍历项目的Python文件,解析它们的抽象语法树(AST),并查找所有对eval函数的调用。一旦找到,就需要进一步分析eval的参数来源。如果参数来源于外部不可信输入(如用户提交的数据、网络请求内容、文件读取等),或者是一个动态构建的字符串,那么这几乎可以肯定是一个安全漏洞。

一个基本的AST扫描器可以这样构建:

立即学习Python免费学习笔记(深入)”;

如何使用Python发现不安全的eval()使用?
import ast
import os

class EvalFinder(ast.NodeVisitor):
    def __init__(self):
        self.eval_calls = []

    def visit_Call(self, node):
        # 检查是否是函数调用
        if isinstance(node.func, ast.Name) and node.func.id == 'eval':
            # 找到一个eval()调用
            # 进一步分析node.args[0]可以判断参数类型
            # 例如,如果是ast.Str,可能是字面量字符串
            # 如果是ast.Name,则参数是一个变量,需要进一步追踪其来源
            self.eval_calls.append({
                'line': node.lineno,
                'col': node.col_offset,
                'args': [ast.dump(arg) for arg in node.args] # 简单展示参数结构
            })
        self.generic_visit(node) # 继续遍历子节点

def find_eval_in_file(filepath):
    with open(filepath, 'r', encoding='utf-8') as f:
        content = f.read()
    try:
        tree = ast.parse(content, filename=filepath)
        finder = EvalFinder()
        finder.visit(tree)
        return finder.eval_calls
    except SyntaxError as e:
        print(f"Error parsing {filepath}: {e}")
        return []

def scan_project_for_eval(project_root):
    all_eval_uses = {}
    for root, _, files in os.walk(project_root):
        for file in files:
            if file.endswith('.py'):
                filepath = os.path.join(root, file)
                eval_uses = find_eval_in_file(filepath)
                if eval_uses:
                    all_eval_uses[filepath] = eval_uses
    return all_eval_uses

# 示例用法:
# project_path = './my_python_project'
# insecure_evals = scan_project_for_eval(project_path)
# for file, calls in insecure_evals.items():
#     print(f"File: {file}")
#     for call in calls:
#         print(f"  Line {call['line']}, Col {call['col']}: eval({call['args']})")

这个AST扫描器能定位到eval的调用点。更复杂的分析会涉及到数据流追踪,例如一个变量被eval调用,但这个变量的值是在程序运行过程中从用户输入、网络请求等外部来源获取的。这超出了纯粹静态分析的范畴,通常需要更专业的静态分析工具或人工代码审查。

Python中的eval()为何被视为不安全函数?

eval()函数在Python中被认为是极其危险的,其核心原因在于它能够执行任意的Python代码。当你把一个字符串传递给eval(),Python解释器会尝试将这个字符串当作一个完整的Python表达式来求值并执行。这意味着,如果攻击者能够控制传递给eval()的字符串内容,他们就可以在你的应用程序运行环境中执行任何他们想执行的代码。

如何使用Python发现不安全的eval()使用?

这听起来可能有点抽象,但想象一下:一个Web应用接收用户提交的查询字符串,然后直接用eval()来处理。如果用户输入的是__import__('os').system('rm -rf /'),那么你的服务器文件系统可能就遭殃了。这可不是开玩笑,而是实实在在的威胁。它不仅仅限于文件操作,还可以是数据泄露(比如读取环境变量、数据库凭证)、权限提升、甚至是在你的服务器上安装恶意软件。

很多人会误以为eval()提供了一个“沙箱”环境,或者通过限制globalslocals参数就能安全使用。但实际情况是,构建一个真正安全的Python沙箱是极其困难的,几乎不可能完美。即使限制了内置函数和全局变量,攻击者也常常能找到绕过的方法,例如通过对象的属性、方法链等来访问受限资源。所以,默认的立场应该是:除非你对输入有绝对的控制且能确保其安全性,否则永远不要使用eval()

网奇IOS智能在线订单系统
网奇IOS智能在线订单系统

产品简介: 网奇IOS智能订单系统,是网奇公司研发的一款智能在线订单编辑以及管理系统。本系统适合使用在;在线报名、酒店预定、信息反馈、在线订单和在线投诉等等诸多应用上。本系统所有选项字段完全通过后台控制,在线报名系统可以变为在线预定系统,同时可以变为任何其它的系统,里面的栏目字段,可以任意添加、删除、 修改。本系统为网奇公司全国独家首创,顺应网络需求,安装十分便利,上传即可使用。产品特色:

下载

静态分析与AST:检测eval()的利器

静态分析,尤其基于抽象语法树(AST)的分析,是发现代码中潜在eval()滥用的最可靠方法之一。不像正则表达式,AST分析能够真正理解代码的结构和语义,避免误报和漏报。Python的ast模块正是为此而生。

当我们用ast.parse()将Python源代码转换为AST时,我们得到的是一个树形结构,每个节点代表了代码中的一个元素,比如一个函数调用、一个变量赋值、一个循环等等。对于eval()的检测,我们关注的是ast.Call节点,它表示一个函数调用。通过遍历这棵树,我们可以很容易地识别出所有名为eval的函数调用。

但仅仅找到eval还不够。一个字面量字符串,比如eval("1 + 1"),虽然使用了eval,但其风险是可控的,因为代码内容是固定的。真正危险的是当eval的参数是变量,或者是一个从外部输入动态构建的字符串时。虽然AST本身无法追踪变量在运行时的具体值,但它可以识别出参数的类型。如果eval的参数不是一个简单的字面量字符串(ast.Str),而是一个变量(ast.Name)、一个函数调用(ast.Call)、一个二进制操作(ast.BinOp)等,那么这就需要引起高度警惕了。

例如,在上面的EvalFinder中,我们捕获了eval的调用及其参数的AST表示。这提供了一个起点,让你能够手动审查这些调用,或者在此基础上构建更复杂的数据流分析,尝试追踪变量的来源。对于大型项目,这样的AST扫描器能快速提供一个“危险清单”,大大提高代码审计的效率。当然,它也有局限性,比如无法处理通过getattr__builtins__等方式动态构造的eval调用,以及无法在编译时确定变量的实际值。

运行时监控与防御策略:不仅仅是发现

发现代码中的eval()使用只是第一步,更重要的是如何处理它们,以及在无法避免时如何进行运行时防御。理想情况下,如果发现不安全的eval(),应该立即将其替换掉。

替换eval()的常见安全替代方案:

  • json.loads()yaml.safe_load() 如果你只是想解析JSON或YAML格式的数据,这些是安全且专用的方法。它们不会执行任意代码。
  • ast.literal_eval() 如果你需要安全地评估只包含Python字面量(字符串、数字、元组、列表、字典、布尔值和None)的表达式,ast.literal_eval()是完美的选择。它会拒绝任何非字面量的表达式,从而避免代码执行。
  • 模板引擎: 对于生成动态HTML或文本内容,使用Jinja2、Django Templates等成熟的模板引擎。它们通常有严格的安全控制,避免任意代码执行。
  • 自定义解析器: 如果数据格式非常特殊,可以编写一个专门的解析器,而不是依赖eval()。这虽然工作量大,但安全性最高。

如果eval()真的不可避免(极少数情况):

  • 严格限制globalslocals eval()函数接受globalslocals参数,可以用来限制可用的全局和局部命名空间。例如,eval(code_str, {"__builtins__": {}}, {})可以创建一个非常受限的环境。但请注意,这并非万无一失的沙箱,经验丰富的攻击者仍可能找到绕过方法。
  • 输入验证与净化: 这是最关键但也是最困难的一点。你必须对所有传递给eval()的输入进行极其严格的验证和净化,确保它只包含预期的数据或表达式,绝不包含任何可执行代码的片段。这通常意味着白名单验证,而不是黑名单(因为你永远无法穷尽所有恶意输入)。
  • 最小权限原则: 运行应用程序的账户应该拥有最小的权限,即使eval()被利用,也能将损害降到最低。

最终,最好的防御策略是避免使用eval()。在绝大多数情况下,都有更安全、更健壮的替代方案。代码审查和开发团队的安全意识培训也至关重要,它们能从源头上减少eval()这种高风险函数的引入。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

745

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

634

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

758

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

617

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1260

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

547

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

577

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

705

2023.08.11

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

80

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 0.6万人学习

Django 教程
Django 教程

共28课时 | 3万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号