议题解读:How I use a novel approach to exploit a limited OOB on Ubuntu at Pwn2Own Vancouver 2024
字数 2318 2025-08-20 18:17:41

Linux内核栈缓冲区越界写漏洞利用技术深度解析

漏洞概述

本议题介绍了一种针对Linux内核栈缓冲区越界写漏洞的新型利用技术,该漏洞在Pwn2Own Vancouver 2024比赛中被成功利用。漏洞存在于Linux内核网络调度器中的nla_parse_nested函数,允许攻击者通过精心构造的用户态数据实现内核栈越界写,最终通过结合内核栈分配机制和eBPF技术实现任意地址写,修改modprobe_path完成提权。

漏洞详细分析

漏洞代码位置

漏洞位于内核处理TAPRIO队列调度器的代码中,具体在解析嵌套netlink属性时的类型处理不当:

struct nla_policy taprio_tc_policy[TCA_TAPRIO_TC_ENTRY_MAX + 1] = {
    [TCA_TAPRIO_TC_ENTRY_INDEX] = { .type = NLA_U32 },
    [TCA_TAPRIO_TC_ENTRY_MAX_SDU] = { .type = NLA_U32 },
    [TCA_TAPRIO_TC_ENTRY_FP] = NLA_POLICY_RANGE(NLA_U32, TC_FP_EXPRESS, TC_FP_PREEMPTIBLE),
};

漏洞成因

  1. 类型转换问题

    • nla_get_u32获取TCA_TAPRIO_TC_ENTRY_INDEX返回u32类型
    • 但接收变量tcint类型
    • 通过提供很大的TCA_TAPRIO_TC_ENTRY_INDEX值可使tc变为负数
  2. 越界访问

    • 绕过后续的tc范围检查
    • 写入max_sdufp数组时使用负数索引导致向前越界写栈内存
    • max_sdufp是内核栈上的数组:u32 max_sdu[TC_QOPT_MAX_QUEUE]u32 fp[TC_QOPT_MAX_QUEUE]

漏洞补丁

补丁通过限制TCA_TAPRIO_TC_ENTRY_INDEX的最大值来修复:

[TCA_TAPRIO_TC_ENTRY_INDEX] = NLA_POLICY_MAX(NLA_U32, TC_QOPT_MAX_QUEUE),

漏洞利用原语分析

漏洞提供的原始利用能力有限:

  1. 写入大小限制

    • 最大只能写入0xffffu32类型)
    • max_sdu写入的值需要小于dev->max_mtu
  2. 写入值限制

    • fp写入的值受taprio_tc_policy约束,只能为1或2
  3. 利用难度

    • 难以部分修改栈上的指针(修改后偏移太大难以控制)
    • 常规的栈越界写利用策略难以奏效

内核内存布局机制

VMALLOC区域特性

  1. 内存分配

    • Linux内核进程栈在VMALLOC区域分配
    • vmalloc接口也在此区域分配内存
    • 不同进程的栈内存、vmalloc堆内存相邻
  2. 保护机制

    • 默认分配时会在内存后添加不可访问的guard page防止溢出
    • 但OOB(越界)写入不受此保护影响

VMALLOC分配/释放机制

  1. 地址空间

    • 虚拟地址空间[VMALLOC_START, VMALLOC_END]
    • 用于分配虚拟地址连续但物理地址不一定连续的内存
  2. 管理结构

    • 已分配的虚拟地址空间用vm_area结构体表示
    • 通过链表和红黑树组织
  3. 分配过程

    • 从低地址向高地址遍历vm_area搜索空闲区间
    • 类似于ptmalloc中的unsorted bin分配机制
    • 通过alloc_page向伙伴系统逐页申请物理内存
  4. 释放过程

    • 物理地址释放回伙伴系统
    • 虚拟地址空间标记为unpurged vm_area
    • 当所有unpurged vm_area页面数超过阈值(约40000页)时才回收
    • 回收前对应的虚拟地址不可被申请

利用技术演进

传统利用方法及其限制

  1. 修改其他进程内核栈

    • 类似SVE-2020-18610的利用策略
    • 修改do_select栈内存实现栈溢出和ROP
  2. 防护机制

    • CONFIG_RANDOMIZE_KSTACK_OFFSET引入栈布局随机性
    • 导致偏移无法确定,阻止此类利用

新型利用技术

  1. VMALLOC区域目标选择

    • 除了内核栈外,VMALLOC还包含:
      • Android Mali GPU驱动管理结构
      • eBPF字节码等
  2. 历史案例参考

    • CVE-2021-33909:通过vmalloc越界写修改eBPF字节码
  3. eBPF利用现状

    • 低权限进程无法直接使用eBPF(因易被用于恶意软件)
    • 但可通过setsockopt创建eBPF字节码(参考CVE-2023-3609)

完整利用链构建

eBPF处理流程

  1. 校验阶段

    • 首先校验字节码的合法性
    • 校验通过后将filter字节码转换为eBPF字节码
  2. JIT编译

    • 将eBPF字节码进行即时编译

漏洞利用关键点

  1. 时机选择

    • 在校验通过后、JIT编译前篡改eBPF字节码
    • 注入恶意eBPF指令实现任意地址写
  2. 指令注入

    • 篡改注入BPF_STX_MEM指令
    • 用于实现任意地址写
  3. 最终目标

    • 修改modprobe_path实现提权

利用过程中的挑战与解决方案

  1. 地址泄露问题

    • 利用CVE-2024-26816泄露内核镜像基地址
  2. 内存布局不稳定

    • 大量进程创建/销毁导致内存布局变化
    • 解决方案:通过SIGSTOP暂停部分进程减少系统行为
  3. 竞争条件

    • 需要在eBPF字节码生成到JIT之间触发漏洞
    • 解决方案:增加bpf指令数目以延长时间窗口

相关漏洞案例

  1. vmalloc区域漏洞利用

    • ioremap越界写修改内核栈:Pwn2Own 2023 Tesla, CVE-2022-21765
    • ION Buffer OOB漏洞:SVE-2020-18610
  2. 利用策略通用性

    • 通过RACE在eBPF生成过程中篡改指令的技术
    • 可应用于其他vmalloc相关漏洞利用场景

总结与启示

  1. 技术要点

    • 结合内核栈分配机制和eBPF实现有限OOB到任意地址写
    • 利用VMALLOC区域特性绕过常规防护
    • 精确控制漏洞触发时机实现稳定利用
  2. 防护建议

    • 加强类型转换检查
    • 增强VMALLOC区域隔离
    • 缩短eBPF校验到JIT的时间窗口
    • 监控modprobe_path等关键数据修改
  3. 研究价值

    • 为受限原语的利用提供新思路
    • 展示内核子系统间交互的安全影响
    • 推动更精细的内核内存防护机制发展
Linux内核栈缓冲区越界写漏洞利用技术深度解析 漏洞概述 本议题介绍了一种针对Linux内核栈缓冲区越界写漏洞的新型利用技术,该漏洞在Pwn2Own Vancouver 2024比赛中被成功利用。漏洞存在于Linux内核网络调度器中的 nla_parse_nested 函数,允许攻击者通过精心构造的用户态数据实现内核栈越界写,最终通过结合内核栈分配机制和eBPF技术实现任意地址写,修改 modprobe_path 完成提权。 漏洞详细分析 漏洞代码位置 漏洞位于内核处理TAPRIO队列调度器的代码中,具体在解析嵌套netlink属性时的类型处理不当: 漏洞成因 类型转换问题 : nla_get_u32 获取 TCA_TAPRIO_TC_ENTRY_INDEX 返回 u32 类型 但接收变量 tc 是 int 类型 通过提供很大的 TCA_TAPRIO_TC_ENTRY_INDEX 值可使 tc 变为负数 越界访问 : 绕过后续的 tc 范围检查 写入 max_sdu 和 fp 数组时使用负数索引导致向前越界写栈内存 max_sdu 和 fp 是内核栈上的数组: u32 max_sdu[TC_QOPT_MAX_QUEUE] 和 u32 fp[TC_QOPT_MAX_QUEUE] 漏洞补丁 补丁通过限制 TCA_TAPRIO_TC_ENTRY_INDEX 的最大值来修复: 漏洞利用原语分析 漏洞提供的原始利用能力有限: 写入大小限制 : 最大只能写入 0xffff ( u32 类型) max_sdu 写入的值需要小于 dev->max_mtu 写入值限制 : fp 写入的值受 taprio_tc_policy 约束,只能为1或2 利用难度 : 难以部分修改栈上的指针(修改后偏移太大难以控制) 常规的栈越界写利用策略难以奏效 内核内存布局机制 VMALLOC区域特性 内存分配 : Linux内核进程栈在VMALLOC区域分配 vmalloc接口也在此区域分配内存 不同进程的栈内存、vmalloc堆内存相邻 保护机制 : 默认分配时会在内存后添加不可访问的guard page防止溢出 但OOB(越界)写入不受此保护影响 VMALLOC分配/释放机制 地址空间 : 虚拟地址空间 [VMALLOC_START, VMALLOC_END] 用于分配虚拟地址连续但物理地址不一定连续的内存 管理结构 : 已分配的虚拟地址空间用 vm_area 结构体表示 通过链表和红黑树组织 分配过程 : 从低地址向高地址遍历 vm_area 搜索空闲区间 类似于ptmalloc中的unsorted bin分配机制 通过 alloc_page 向伙伴系统逐页申请物理内存 释放过程 : 物理地址释放回伙伴系统 虚拟地址空间标记为 unpurged vm_area 当所有 unpurged vm_area 页面数超过阈值(约40000页)时才回收 回收前对应的虚拟地址不可被申请 利用技术演进 传统利用方法及其限制 修改其他进程内核栈 : 类似SVE-2020-18610的利用策略 修改 do_select 栈内存实现栈溢出和ROP 防护机制 : CONFIG_RANDOMIZE_KSTACK_OFFSET 引入栈布局随机性 导致偏移无法确定,阻止此类利用 新型利用技术 VMALLOC区域目标选择 : 除了内核栈外,VMALLOC还包含: Android Mali GPU驱动管理结构 eBPF字节码等 历史案例参考 : CVE-2021-33909:通过vmalloc越界写修改eBPF字节码 eBPF利用现状 : 低权限进程无法直接使用eBPF(因易被用于恶意软件) 但可通过 setsockopt 创建eBPF字节码(参考CVE-2023-3609) 完整利用链构建 eBPF处理流程 校验阶段 : 首先校验字节码的合法性 校验通过后将filter字节码转换为eBPF字节码 JIT编译 : 将eBPF字节码进行即时编译 漏洞利用关键点 时机选择 : 在校验通过后、JIT编译前篡改eBPF字节码 注入恶意eBPF指令实现任意地址写 指令注入 : 篡改注入 BPF_STX_MEM 指令 用于实现任意地址写 最终目标 : 修改 modprobe_path 实现提权 利用过程中的挑战与解决方案 地址泄露问题 : 利用CVE-2024-26816泄露内核镜像基地址 内存布局不稳定 : 大量进程创建/销毁导致内存布局变化 解决方案:通过 SIGSTOP 暂停部分进程减少系统行为 竞争条件 : 需要在eBPF字节码生成到JIT之间触发漏洞 解决方案:增加bpf指令数目以延长时间窗口 相关漏洞案例 vmalloc区域漏洞利用 : ioremap越界写修改内核栈:Pwn2Own 2023 Tesla, CVE-2022-21765 ION Buffer OOB漏洞:SVE-2020-18610 利用策略通用性 : 通过RACE在eBPF生成过程中篡改指令的技术 可应用于其他vmalloc相关漏洞利用场景 总结与启示 技术要点 : 结合内核栈分配机制和eBPF实现有限OOB到任意地址写 利用VMALLOC区域特性绕过常规防护 精确控制漏洞触发时机实现稳定利用 防护建议 : 加强类型转换检查 增强VMALLOC区域隔离 缩短eBPF校验到JIT的时间窗口 监控 modprobe_path 等关键数据修改 研究价值 : 为受限原语的利用提供新思路 展示内核子系统间交互的安全影响 推动更精细的内核内存防护机制发展