艾体宝洞察 | “顶会”看安全(四):Black hat-揭示 PyTorch 中 TorchScript 引擎的潜在风险

一、pytorch如何保存训练模型

最初pytorch用pickle模块进行临时保存程序中的对象(比如训练好的模型、中间计算结果),方便后续直接加载使用。pickle是 Python 的序列化 / 反序列化模块,核心作用是把 Python 对象(比如字典、列表、类实例等)转换成字节流(序列化,称为 "pickling"),或者把字节流恢复成原来的 Python 对象(反序列化,称为 "unpickling")。

但是pickle进行模型临时保存会面临一些明显的安全问题,恶意构造的 pickle 数据在反序列化(unpickle)时会执行任意代码,如下图所示:

因此,weights_only参数被引入,以限制反序列化的内容,仅允许加载张量(torch.Tensor)、基本数据类型(int/float/str 等)、简单容器(dict/list/tuple),禁止加载自定义类、函数、复杂对象等可能包含可执行代码的内容。作为对比,

二、weights_only为什么有效

这里我们解释为什么weights_only为什么有效之前,需要先说明为什么pickle不安全,pickle 里最危险的两类能力GLOBAL和REDUCE,GLOBAL可以引用任意模块里的任意对象(函数/类),例如 os.system、subprocess.Popen、builtins.eval,REDUCE可以调用一个函数(或可调用对象)并传入参数来"构造对象"。这个"函数"如果被引用成 os.system 之类,就等于反序列化过程中直接执行命令。

所以普通的 torch.load()(weights_only=False 的老逻辑)在读取恶意 .pt/.pth 时,会把这些 pickle 指令照做,导致典型的 反序列化 RCE。

而weights_only的有效机制也是主要禁用这两个函数,如下图所示,如果pickle指令里面有['sys','os','posix','nt'] 这种高危模块黑名单,就会直接raise UnpicklingError。如果利用白名单机制则可以进一步限制危险函数。

三、TorchScript 的风险

weights_only看似杜绝了pytorch在加载模型时存在反序列化漏洞的风险,但是通过分析torch.load()函数,能够发现这里有一个分流的逻辑,如果不是 TorchScript zip,才直接轮到 weights_only 起作用。而如果 zip 被识别为 TorchScript(JIT)格式,会先直接执行torch.jit.load(),并不执行weights_only的安全限制。

所以如果我们能够构建一个TorchScript zip 文件,通过 _is_torchscript_zip() 的格式检测,但内部包含可被 pickle / Python 反序列化处理的恶意结构,就能实现反序列化漏洞利用。

那么首先我们要说明什么是TorchScript ,TorchScript 是 PyTorch 为跨语言、无 Python 环境执行而设计的中间表示(IR),其初衷是避免 Python 动态执行与 pickle 风险。如下图所示

为了构建这样恶意的TorchScript zip文件,我们首先要了解TorchScript长什么样。从原始的python代码到最后TorchScript的IR图,大概需要经过四步:

1.python代码->python AST的转化:Python 解释器会先把代码解析成Python 的抽象语法树(AST),这是 Python 对代码结构的 "结构化表示",这里能看到函数定义、参数、条件分支、返回语句等内容,但不是pytorch JIT能直接用的格式。

2.python AST->JIT AST(TorchScript 的中间表示):这是 PyTorch 专用的结构化表示,包含了 JIT 能理解的 "函数定义""参数""变量类型""运算逻辑" 等信息,转换后,JIT 可以对这段代码做编译优化、跨平台部署

3.JIT AST->original IR graph:从 "语法结构" 到 "计算执行图" 的翻译,核心步骤是遍历 AST 解析语法 → 生成 IR 节点和数据流 → 处理控制流 → 填充类型信息

4.original IR graph->optimized IR graph:PyTorch JIT 的优化器会对原始 IR 做静态分析 + 代码简化,消除了冗余的变量加载 / 存储,简化了控制流逻辑,保留核心计算逻

TorchScript 的序列化流程,即把编译好的模型(IR、函数)保存为文件,方便后续加载 / 部署的过程。首先是"IR / 函数 → 保存为文件 → 恢复为模型" 的闭环,

  1. 输入:已经编译好的IR graph(中间表示)、ScriptFunction(TorchScript 函数);

  2. 封装:这些内容会被打包成ScriptModule(TorchScript 的模块对象);

  3. 保存:通过torch.save()把ScriptModule存为文件(如module.pt);

  4. 加载:之后用torch.load()可以把文件恢复为ScriptModule,直接使用;

在执行torch.save()时,会有操作如下:

  1. ScriptFunction(函数)添加到ScriptModule中;

  2. 通过ScriptModuleSerializer::serialize()(序列化器),把ScriptModule拆分为 3 部分存储:

    1. data.pkl:保存模型的值信息(用IValue表示,是 TorchScript 中统一的 "值" 类型);

    2. code/目录:保存Python 代码 / 调试信息(方便后续导出可读代码);

    3. constants.pkl:保存模型中的常量张量(比如代码里的固定参数)

那么后续在执行torch.load()操作时,会有重新反序列化的操作,核心逻辑是通过调用ScriptModuleDeserializer::deserialize 这个方法,调用 readArchive 方法进行反序列化,读取 constants.pkl、data.pkl 文件

在之前TorchScript构建的说明时,从最后的optimized IR graph也能看出,里面的核心计算逻辑不再是python函数,而是torch.add, torch.mul, aten::add, prim::If 此类Operator(算子),由 C++ / ATen / JIT runtime 实现,在 TorchScript IR 里以 OP 指令的形式出现,Operators 通过 RegisterOperators 注册。这意味着所有 TorchScript 可用算子必须 显式注册,注册时绑定到具体 C++ 实现。JIT 在执行 IR 时,只能调用已注册算子,不能随意调用 Python 函数。

这种通过原子方式调用看似安全,但是细究就能发现存在风险点,本次的漏洞主要出现在aten::save和aten::from_file两个原子方式上。aten::save用于在 TorchScript 中保存 tensor / object,而aten::from_file则用于从文件加载数据(tensor / storage)

为了调用这两个方法,我们利用torch.from_file和torch.save两个函数即可。通过在torchscript进行这两个函数的调用,我们可以即可实现RCE等漏洞。

五、艾体宝Mend.io价值

从此次漏洞事件来看,AI项目中的许多安全漏洞源于第三方库,尤其是深度学习框架(如 PyTorch、TensorFlow)和数据处理工具(如 Pandas、NumPy)。Mend.io 可以深入分析项目中的所有第三方依赖,识别其中的已知漏洞和安全隐患。通过自动化漏洞扫描和依赖分析,Mend.io 能帮助开发团队及时发现并修复潜在的安全风险。

相关推荐
农场主John8 小时前
Accelerate_deepspeed使用
pytorch·llm·deepspeed
康谋自动驾驶8 小时前
高校自动驾驶研究新基建:“实测 - 仿真” 一体化数据采集与验证平台
人工智能·机器学习·自动驾驶·科研·数据采集·时间同步·仿真平台
Ftsom8 小时前
【6】kilo 上下文管理与压缩机制
人工智能·agent·ai编程·kilo
shangjian0078 小时前
AI-大语言模型LLM-Transformer架构1-整体介绍
人工智能·语言模型·transformer
机 _ 长8 小时前
YOLO26 蒸馏改进全攻略:从理论到实战 (Response + Feature + Relation)
人工智能·深度学习·yolo·目标检测·计算机视觉
shangjian0078 小时前
AI-大语言模型LLM-Transformer架构2-自注意力
人工智能·语言模型·transformer
2501_941507948 小时前
基于YOLOv26的文档手写文本与签名识别系统·从模型改进到完整实现
人工智能·yolo·目标跟踪
_ziva_8 小时前
Layer Normalization 全解析:LLMs 训练稳定的核心密码
人工智能·机器学习·自然语言处理
莫潇羽8 小时前
Midjourney AI图像创作完全指南:从零基础到精通提示词设计与风格探索
人工智能·midjourney
加加今天也要加油8 小时前
Oinone × AI Agent 落地指南:元数据即 Prompt、BPM 状态机护栏、SAGA 补偿、GenUI
人工智能·低代码·prompt