在linux内核中利用递归
字数 1935 2025-08-20 18:17:07
Linux内核递归利用漏洞分析与利用教学
1. 漏洞背景与前提条件
1.1 Linux内核堆栈特性
Linux内核堆栈与用户空间堆栈有显著差异:
-
大小限制:
- 32位x86架构:4096-8192字节
- x86-64架构:16384字节
- 由
THREAD_SIZE_ORDER和THREAD_SIZE宏定义
-
分配方式:
- 使用内核的buddy分配器分配
- 没有防护页(guard page)保护
- 溢出会导致与正常数据重叠
1.2 堆叠文件系统(Stacked Filesystem)
- 定义:将另一个文件系统中的文件夹作为后备存储的文件系统
- 常见类型:
- ecryptfs:透明加密文件系统
- overlayfs:合并多个文件系统的统一视图
- 潜在风险:
- 每层文件系统都会增加内核堆栈深度
- 可能导致内核堆栈溢出
- 防护措施:
- 通过
FILESYSTEM_MAX_STACK_DEPTH限制嵌套层数(默认最多两层)
- 通过
1.3 procfs特殊文件
/proc/[pid]/mem:暴露进程的整个虚拟地址空间/proc/[pid]/environ:暴露进程的环境变量内存区域(mm->env_start到mm->env_end)/proc/[pid]/cmdline:暴露进程的命令行参数内存区域(mm->arg_start到mm->arg_end)
2. 漏洞原理
2.1 漏洞形成机制
-
ecryptfs的mmap特性:
- ecryptfs支持mmap操作
- 不能简单转发到底层文件系统的mmap处理程序
- 需要自己的页面缓存进行映射
- 处理页面错误时使用底层文件系统的VFS读处理程序(
kernel_read())
-
攻击链构建:
- 创建进程A,设置其环境变量区域指向有效加密数据
- 以
/proc/$A为底层文件系统创建ecryptfs挂载点 - 将
/tmp/$A/environ映射到进程B的内存 - 重复此过程构建多层映射链
-
递归触发:
- 进程C访问映射区域触发页面错误
- 错误处理导致ecryptfs从
/proc/$B/environ读取 - 进而导致进程B中的页面错误
- 继续递归直到内核堆栈溢出
2.2 关键突破点
-
环境变量区域控制:
- 使用
prctl(PR_SET_MM, PR_SET_MM_MAP...)设置arg_start、arg_end、env_start和env_end - 允许将proc文件指向任意虚拟内存范围
- 使用
-
堆栈布局利用:
- 精确控制递归深度
- 利用堆栈帧中的"洞"避免破坏关键数据(如canary和thread_info结构)
3. 漏洞利用技术
3.1 利用步骤
-
设置初始进程:
- 创建进程A,加载有效加密的ecryptfs文件到其内存
- 配置环境区域指向该加密数据
-
构建ecryptfs挂载:
- 以
/proc/$A为底层文件系统创建ecryptfs挂载点 - 访问
/tmp/$A/environ获取解密视图
- 以
-
创建映射链:
- 将解密视图映射到进程B的内存
- 重复此过程构建多层映射
-
触发递归:
- 在链的末端使用FUSE映射暂停执行
- 通过管道分配内存覆盖堆栈
-
控制执行流:
- 精确覆盖返回地址
- 绕过KASLR(若未启用)
- 保持
addr_limit为KERNEL_DS
3.2 关键技术细节
-
堆栈对齐技巧:
- 混合使用
environ和cmdline文件(不同堆栈帧大小) - 结合
write()系统调用和VFS写入处理程序控制深度
- 混合使用
-
内存操作原语:
void kernel_write(unsigned long addr, char *buf, size_t len) { int pipefds[2]; pipe(pipefds); write(pipefds[1], buf, len); close(pipefds[1]); read(pipefds[0], (char *)addr, len); close(pipefds[0]); } -
权限提升:
- 覆盖coredump处理程序
- 触发SIGSEGV以root权限执行处理程序
char *core_handler = "|/tmp/crash_to_root"; kernel_write(0xffffffff81e87a60, core_handler, strlen(core_handler)+1);
4. 漏洞修复
-
补丁1 (2f36db710093):
- 禁止在没有mmap处理程序的情况下通过ecryptfs打开文件
-
补丁2 (e54ad7f1ee26):
- 禁止在procfs之上堆叠任何文件系统
-
长期防护建议:
- 在内核堆栈添加防护页
- 将thread_info结构从堆栈底部移除
5. 教学总结
关键知识点
- 理解Linux内核堆栈与用户空间堆栈的区别
- 掌握堆叠文件系统的工作原理和安全影响
- 学习procfs特殊文件的访问机制
- 掌握通过递归触发内核堆栈溢出的技术
- 学习精确控制堆栈布局和绕过防护的技术
实践建议
- 在实验环境中复现漏洞时,注意内核版本和配置
- 研究不同架构下的堆栈布局差异
- 探索现代内核防护机制(如KASLR、stack canary)的绕过技术
- 分析其他类型的递归导致的内核漏洞
防御措施
- 及时应用内核安全更新
- 启用所有可用的内核安全特性(KASLR等)
- 限制非特权用户的特殊文件系统访问
- 监控系统调用和proc文件访问的异常模式