Cross cache Attack技术细节分析
字数 2035 2025-08-22 12:22:54

Cross Cache Attack 技术深度分析与实践指南

1. 技术概述

Cross Cache Attack(跨缓存攻击)是一种针对Linux内核SLUB分配器的高级利用技术,通过精心控制slab页面的分配与释放过程,实现将目标slab页面释放回伙伴系统(buddy system),然后重新申请该页面用于其他用途的攻击方法。

2. 前置知识

2.1 SLUB分配器核心概念

  • slab:内存管理的基本单位,由单个或多个连续页面组成
  • object:slab中分配的实际内存单元
  • cpu_partial:每个CPU部分空闲slab链表的最大数量阈值
  • objs_per_slab:每个slab中包含的object数量
  • partial list:部分空闲的slab链表

2.2 关键数据结构

struct kmem_cache {
    unsigned int cpu_partial;  // 每个CPU partial列表中的最大slab数量
    struct kmem_cache_order_objects oo;  // 包含order和objects_per_slab信息
    // ... 其他字段
};

struct page {
    void *freelist;     // 空闲对象链表
    unsigned counters;  // 包含inuse、frozen等状态
    // ... 其他字段
};

3. 攻击原理与技术细节

3.1 核心攻击流程

  1. 释放slab page:通过特定操作将目标slab释放回伙伴系统
  2. 重新申请页面:从伙伴系统中重新获取该页面用于其他目的
  3. 实现跨缓存控制:利用页面重用实现不同类型对象间的控制

3.2 关键技术步骤

步骤1:申请(cpu_partial+1) * objs_per_slab个objects

  • 目的:占用足够多的slab,为后续操作做准备
  • 计算公式:(cpu_partial + 1) * objs_per_slab
  • 结果:占用14个完整slab,第15个slab不满

步骤2:申请objs_per_slab-1个objects

  • 目的:使部分slab接近满状态
  • 操作:继续申请直到一个slab几乎满

步骤3:申请UAF object

  • 目的:创建待利用的对象
  • 位置:该对象位于第16个slab中
  • 关键点:记录该对象及其所在页面的地址

步骤4:申请objs_per_slab + 1个objects

  • 目的:使UAF object所在的slab页满载
  • 效果:确保后续释放操作能触发特定路径

步骤5:释放UAF object

  • 关键行为:触发put_cpu_partial()但未达到阈值
  • 结果:slab被挂载到partial链上

步骤6:释放UAF object所在页的所有object

  • 目的:使目标slab变为空状态
  • 操作:释放该页面上所有其他object

步骤7:释放1-14 slabs中各一个object

  • 关键机制:
    • 每个释放操作触发put_cpu_partial()
    • 达到cpu_partial阈值(13)后触发unfreeze_partials()
    • 空slab被discard_slab()释放回伙伴系统

4. 代码实现分析

4.1 关键内核API

// 创建专用缓存
kmem_cache_create("name", size, align, flags, ctor);

// 从缓存分配对象
kmem_cache_alloc(cachep, flags);

// 释放对象回缓存
kmem_cache_free(cachep, obj);

// 从伙伴系统分配页面
alloc_pages(GFP_KERNEL, order);

// 获取页面虚拟地址
page_address(page);

4.2 攻击演示代码关键部分

// 步骤1:初始分配
for (i = 0; i < (cpu_partial + 1) * objs_per_slab; i++) {
    ds_list[ds_sp++] = kmem_cache_alloc(my_cache_ptr, GFP_KERNEL);
}

// 步骤3:创建UAF对象
uaf_object = kmem_cache_alloc(my_cache_ptr, GFP_KERNEL);
target_page_virt = (void*)((unsigned long)uaf_object & ~(unsigned long)(page_size - 1));

// 步骤5-7:精心控制的释放过程
kmem_cache_free(my_cache_ptr, uaf_object);
// ... 其他释放操作

// 重新申请目标页面
realloc_page = alloc_pages(GFP_KERNEL, page_order);
realloc_page_virt = page_address(realloc_page);

5. 内核源码关键路径分析

5.1 释放路径调用链

kmem_cache_free()
    slab_free()
        do_slab_free()
            __slab_free()
                put_cpu_partial()
                unfreeze_partials()
                    discard_slab()
                        free_slab()
                            __free_pages()  // 最终释放到伙伴系统

5.2 关键函数逻辑

__slab_free():

  • 检查slab状态(frozen, inuse等)
  • 决定是否进入put_cpu_partial()
  • 处理满slab释放第一个object的情况

put_cpu_partial():

  • 维护per-CPU partial链表
  • 检查pobjects > slub_cpu_partial(s)阈值
  • 触发unfreeze_partials()当超过阈值时

unfreeze_partials():

  • 将partial slabs转移到节点列表
  • 对空slab(!new.inuse)调用discard_slab()
  • 需要满足n->nr_partial >= s->min_partial

6. 防御与缓解措施

  1. SLUB加固选项

    • CONFIG_SLUB_DEBUG:启用调试检查
    • CONFIG_SLUB_HARDENED:强化安全性
  2. 内核参数调整

    • 增加cpu_partial阈值
    • 调整min_partial
  3. 代码审计重点

    • __slab_free()中的状态转换
    • unfreeze_partials()的空slab处理逻辑

7. 实际应用场景

  1. 类型混淆攻击
  2. Use-after-free漏洞利用
  3. 内核提权漏洞利用
  4. 容器逃逸攻击

8. 相关CVE案例

  • CVE-2022-29582
  • CVE-2021-20226 (io_uring权限提升)

9. 扩展思考

  1. 与页表攻击的结合:如何利用该技术实现页表控制
  2. 在多核环境下的变种:针对SMP系统的优化攻击
  3. 新型防御机制的绕过:针对现有防护措施的对抗技术

10. 实验环境搭建建议

  1. 内核版本:5.15.0-122(与示例代码兼容)
  2. 调试工具:
    • slabinfo查看slab状态
    • gdb内核调试
    • crash工具分析内存状态
  3. 测试模块:确保可加载内核模块功能开启

通过深入理解Cross Cache Attack的技术细节,安全研究人员可以更好地评估内核内存管理的安全性,并开发更有效的防御机制。

Cross Cache Attack 技术深度分析与实践指南 1. 技术概述 Cross Cache Attack(跨缓存攻击)是一种针对Linux内核SLUB分配器的高级利用技术,通过精心控制slab页面的分配与释放过程,实现将目标slab页面释放回伙伴系统(buddy system),然后重新申请该页面用于其他用途的攻击方法。 2. 前置知识 2.1 SLUB分配器核心概念 slab :内存管理的基本单位,由单个或多个连续页面组成 object :slab中分配的实际内存单元 cpu_ partial :每个CPU部分空闲slab链表的最大数量阈值 objs_ per_ slab :每个slab中包含的object数量 partial list :部分空闲的slab链表 2.2 关键数据结构 3. 攻击原理与技术细节 3.1 核心攻击流程 释放slab page :通过特定操作将目标slab释放回伙伴系统 重新申请页面 :从伙伴系统中重新获取该页面用于其他目的 实现跨缓存控制 :利用页面重用实现不同类型对象间的控制 3.2 关键技术步骤 步骤1:申请(cpu_ partial+1) * objs_ per_ slab个objects 目的:占用足够多的slab,为后续操作做准备 计算公式: (cpu_partial + 1) * objs_per_slab 结果:占用14个完整slab,第15个slab不满 步骤2:申请objs_ per_ slab-1个objects 目的:使部分slab接近满状态 操作:继续申请直到一个slab几乎满 步骤3:申请UAF object 目的:创建待利用的对象 位置:该对象位于第16个slab中 关键点:记录该对象及其所在页面的地址 步骤4:申请objs_ per_ slab + 1个objects 目的:使UAF object所在的slab页满载 效果:确保后续释放操作能触发特定路径 步骤5:释放UAF object 关键行为:触发 put_cpu_partial() 但未达到阈值 结果:slab被挂载到partial链上 步骤6:释放UAF object所在页的所有object 目的:使目标slab变为空状态 操作:释放该页面上所有其他object 步骤7:释放1-14 slabs中各一个object 关键机制: 每个释放操作触发 put_cpu_partial() 达到 cpu_partial 阈值(13)后触发 unfreeze_partials() 空slab被 discard_slab() 释放回伙伴系统 4. 代码实现分析 4.1 关键内核API 4.2 攻击演示代码关键部分 5. 内核源码关键路径分析 5.1 释放路径调用链 5.2 关键函数逻辑 __ slab_ free() : 检查slab状态(frozen, inuse等) 决定是否进入 put_cpu_partial() 处理满slab释放第一个object的情况 put_ cpu_ partial() : 维护per-CPU partial链表 检查 pobjects > slub_cpu_partial(s) 阈值 触发 unfreeze_partials() 当超过阈值时 unfreeze_ partials() : 将partial slabs转移到节点列表 对空slab( !new.inuse )调用 discard_slab() 需要满足 n->nr_partial >= s->min_partial 6. 防御与缓解措施 SLUB加固选项 : CONFIG_SLUB_DEBUG :启用调试检查 CONFIG_SLUB_HARDENED :强化安全性 内核参数调整 : 增加 cpu_partial 阈值 调整 min_partial 值 代码审计重点 : __slab_free() 中的状态转换 unfreeze_partials() 的空slab处理逻辑 7. 实际应用场景 类型混淆攻击 Use-after-free漏洞利用 内核提权漏洞利用 容器逃逸攻击 8. 相关CVE案例 CVE-2022-29582 CVE-2021-20226 (io_ uring权限提升) 9. 扩展思考 与页表攻击的结合 :如何利用该技术实现页表控制 在多核环境下的变种 :针对SMP系统的优化攻击 新型防御机制的绕过 :针对现有防护措施的对抗技术 10. 实验环境搭建建议 内核版本:5.15.0-122(与示例代码兼容) 调试工具: slabinfo 查看slab状态 gdb 内核调试 crash 工具分析内存状态 测试模块:确保可加载内核模块功能开启 通过深入理解Cross Cache Attack的技术细节,安全研究人员可以更好地评估内核内存管理的安全性,并开发更有效的防御机制。