拓冰建站拓冰建站
首页 / 资讯中心 / 正文

PaddlePaddle 安全通告深度解析:PDSA-2023-002(CVE-2023-38670)——paddle.flip 空指针解引用漏洞的原理与修复

PaddlePaddle 安全通告深度解析PDSA-2023-002CVE-2023-38670——paddle.flip 空指针解引用漏洞的原理与修复【免费下载链接】PaddlePArallel Distributed Deep LEarning: Machine Learning Framework from Industrial Practice 『飞桨』核心框架深度学习机器学习高性能单机、分布式训练和跨平台部署项目地址: https://gitcode.com/GitHub_Trending/pa/Paddle本篇技术文章围绕飞桨PaddlePaddle官方安全通告 PDSA-2023-002 展开paddle.flip算子中因axis参数缺少有效范围校验而触发的空指针解引用漏洞CVE-2023-38670。读完本文你将理解该漏洞的完整触发路径——从 Python 层 PoC 构造、CPU 内核中bitset越界索引的底层机制到InferMeta层的参数校验防线与 2.5.0 版本的补丁边界并掌握升级验证与输入硬化的实操方法。一、漏洞概览PDSA-2023-002 是飞桨安全团队发布的官方安全通告之一原始文档位于 security/advisory/pdsa-2023-002_cn.md英文版本为 security/advisory/pdsa-2023-002.md。通告的核心事实如下项目内容通告编号PDSA-2023-002CVE 编号CVE-2023-38670漏洞类型空指针解引用Null pointer dereference受影响算子paddle.flip后果程序运行时崩溃DoS 性质补丁 Commited96baeed19b4e11b6cbc2dcc6776245ba5fab13修复版本飞桨 2.5.0 起包含该修复该漏洞由 ShanghaiTech University 的 Tong Liu 提交。通告同时指引用户参考 SECURITY_cn.md 获取安全信息总览与问题联系方式飞桨完整的安全通告体系收录在 security/ 目录下。需要强调的是这是一个拒绝服务DoS类漏洞——恶意构造的输入可以让推理/训练进程直接崩溃但不涉及任意代码执行。对于把 Paddle 服务暴露在不可信输入环境如在线推理服务接受用户提交张量元信息的场景这类崩溃型漏洞仍然值得严肃对待。二、复现 PoC 与触发条件分析通告中给出了完整的 PoCProof of Conceptimport paddle import numpy as np from paddle import flip x (paddle.to_tensor(np.random.uniform(-10, 10, [1, 2, 3]).astype(np.int64)),) axis paddle.to_tensor( np.random.uniform(-2147483648, 2147483647, [3, 3]).astype(np.int32) ) flip(x, axis)逐行拆解这个 PoC 的构造意图输入张量x形状为[1, 2, 3]的一维张元组秩rank为 3。按照flip的语义合法的axis取值范围应为[-3, 3)即只能是对 3 个维度有意义的整数索引。攻击核心axisPoC 将axis构造为一个张量而非 Python 整数列表其元素值被随机采样在int32的整个取值范围[-2147483648, 2147483647]内。由于采样区间远大于合法范围[-3, 3)axis中几乎必然存在大量越界值例如-2147483648、2000000000等。触发方式直接调用flip(x, axis)。在存在漏洞的版本中这条调用链上的参数校验未能拦截越界的axis值异常值一路传递到底层内核最终引发崩溃。这里的关键洞察是漏洞的根源不在于flip的数学语义而在于框架层对axis参数范围校验的缺失。axis允许以张量形式传入框架需要将其解包unpack为整数列表后才能进入 C 执行路径而 PoC 正是利用了越界整数值在这条链路上的穿透能力。三、源码级触发路径分析结合当前仓库源码可以完整还原该漏洞的触发路径。整体调用链为Python API → 框架层axis解包与 InferMeta 校验→ 算子内核FlipKernel。3.1 CPU 内核bitset越界索引是崩溃的直接现场flip的 CPU 内核实现在 paddle/phi/kernels/cpu/flip_kernel.cc。其核心逻辑是先用位集bitset标记哪些维度需要翻转再逐元素计算目标偏移constexpr size_t dim_bitset_size 64; template typename T, typename Context void FlipKernel(const Context dev_ctx, const DenseTensor x, const std::vectorint axis, DenseTensor* out) { auto x_dims x.dims(); const int total_dims x_dims.size(); std::bitsetdim_bitset_size dim_bitset; for (auto item : axis) { auto dim item; if (item 0) { dim total_dims; // 负轴号归一化dim item rank } dim_bitset[dim] true; // 关键风险点dim 未做范围检查即用于索引 } // ... 随后基于 dim_bitset 计算每个元素的翻转偏移 }注意这段代码的隐含假设item 0时执行dim item total_dims做负索引归一化。当item是-2147483648这样的极端负数时dim 3仍然是一个大负数当item是正的大数时dim更是远超bitset容量 64。随后dim_bitset[dim] true以越界索引访问std::bitset——dim作为整型会先隐式转换为size_t负值变成一个巨大的无符号数。从源码结构看这种越界访问要么抛出std::out_of_range异常、要么触发未定义行为最终表现为进程崩溃这正是通告所述空指针解引用导致程序运行时崩溃的底层现场。同样的内核模式也存在于 GPU 与 XPU 后端可参考 paddle/phi/kernels/gpu/flip_kernel.cu 和 paddle/phi/kernels/xpu/flip_kernel.cc说明该校验防线必须建在内核执行之前的框架层。3.2 InferMeta 层axis合法范围校验防线修复后axis的范围校验被前置到形状推断InferMeta阶段。当前仓库中 paddle/phi/infermeta/unary.cc 的FlipInferMeta实现了显式的双边界检查void FlipInferMeta(const MetaTensor x, const std::vectorint axis, MetaTensor* out) { auto x_dims x.dims(); auto flip_dims axis; size_t flip_dims_size axis.size(); if (flip_dims_size 0) { // check if dims axis within range auto min_max_d std::minmax_element(flip_dims.begin(), flip_dims.end()); PADDLE_ENFORCE_LT(*min_max_d.first, x_dims.size(), common::errors::InvalidArgument( min(axes) should be less than the input tensor Xs axes of FlipOp. ...)); PADDLE_ENFORCE_GE(*min_max_d.first, x_dims.size() * -1, common::errors::InvalidArgument( min(axes) should be greater than or equal to the input tensor Xs axes of FlipOp times -1. ...)); PADDLE_ENFORCE_LT(*min_max_d.second, x_dims.size(), common::errors::InvalidArgument( max(axes) should be less than the input tensor Xs axes of FlipOp. ...)); // ... 后续计算输出 shape } // ... }其校验规则与flip的语义严格一致下界min(axes) -rank对应负索引最小可到-rank上界max(axes) rank对应正索引最大为rank - 1。一旦越界框架会通过PADDLE_ENFORCE_*抛出带明确错误信息的InvalidArgument异常而非让非法值下沉到内核层把崩溃转化为可预期的、信息充分的参数错误。以 PoC 为例对 rank3 的输入-2147483648会直接命中min(axes) -3的断言异常在形状推断阶段即被拦截FlipKernel根本不会被执行。四、补丁内容与版本边界按照通告该问题在 commited96baeed19b4e11b6cbc2dcc6776245ba5fab13中完成修复修复将包含在飞桨 2.5.0 版本当中。结合当前仓库代码结构可以确认FlipInferMeta中成对的下界/上界断言见上一节正是修复后的防护形态越界axis在 InferMeta 阶段即被InvalidArgument异常拦截内核层的bitset索引不再可能收到非法值。由此可以给出清晰的版本边界判断受影响版本2.5.0 之前发布、且flip调用链上缺少该范围校验的版本安全版本2.5.0 及以上版本。验证修复是否生效升级后可用一段良性化的 PoC 验证校验逻辑已就位——将axis换成一个明显越界但类型合法的值预期得到参数错误而非崩溃import paddle x paddle.to_tensor([[[1, 2, 3], [4, 5, 6]]]) # rank 2 try: paddle.flip(x, [-100]) # 远超合法范围 [-2, 2) except Exception as e: print(type(e).__name__, str(e)[:80]) # 预期抛出 InvalidArgument 类参数错误进程存活修复后的正确行为是抛出带 min(axes) should be greater than or equal to the input tensor Xs axes of FlipOp times -1 一类提示的参数异常而不是进程崩溃。五、安全响应与工程加固建议升级到安全版本直接方式是将飞桨升级到 2.5.0 或更高版本这是消除该漏洞的根治手段。对外服务做输入面收敛如果业务允许用户间接控制参与flip以及任何接受axis/perm等维度参数算子的参数应在应用层先做白名单校验如all(-rank a rank for a in axis)把框架异常拦截在最外层避免异常向上传播影响服务状态。关注安全通告渠道飞桨的所有安全通告统一维护在 security/advisory/ 目录下含中/英/日三语版本安全政策与漏洞报告流程详见 SECURITY_cn.md。本次通告 PDSA-2023-002 的编号规则PDSA PaddlePaddle Security Advisory按年份顺序编号也与目录下 2022–2023 共 20 余篇通告保持一致便于安全团队做批量追踪。对内核开发者的启示本漏洞是一个典型的参数校验未前置案例——底层 flip_kernel.cc 中dim_bitset[dim] true的写法依赖调用方保证dim ∈ [0, rank)。对这类依赖上游校验的内核代码正确的防御姿势是在 InferMeta/框架入口处用PADDLE_ENFORCE_*建立显式契约使非法输入以可读异常的形式在边界处终止。六、小结PDSA-2023-002CVE-2023-38670揭示了paddle.flip在axis参数以张量形式传入且值越界时的崩溃风险越界整型值穿透校验层后在 CPU 内核的std::bitset索引处引发空指针解引用式崩溃。修复通过 commited96baeed19b4e11b6cbc2dcc6776245ba5fab13落地并在 2.5.0 版本中以 InferMeta 阶段的双边界断言min(axes) -rank、max(axes) rank形式建立防护。对用户而言升级至 2.5.0 即完成修复对开发者而言该案例展示了维度类参数校验前置、边界显式这一防御模式在深度学习框架 C 内核开发中的重要性。【免费下载链接】PaddlePArallel Distributed Deep LEarning: Machine Learning Framework from Industrial Practice 『飞桨』核心框架深度学习机器学习高性能单机、分布式训练和跨平台部署项目地址: https://gitcode.com/GitHub_Trending/pa/Paddle创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门