标签:平台 lists .so 本地 没有 getenv 令行 eal 全栈
原文:https://seclists.org/oss-sec/2018/q3/274
Qualys研究实验室的安全团队发现一个位于Linux内核函数create_elf_tables()中的整型溢出漏洞。在64位系统下,本地攻击者可能利用该漏洞通过SUID-root程序获取root权限。
只有内核commit b6a2fea39318 (mm:可变参数长度,2007),但是没有commit da029c11e6b1(exec:限制arg stack最多使用 75% 的 _STK_LIM,2017) 可被利用
绝大多数Linux发行版commit da029c11e6b1 在他们长期支持的内核中,但是 Red Hat Enterprise Linux 和 CentOS 并没有,因此这两个发行版中,容易受到攻击。
150 #define STACK_ROUND(sp, items) 151 (((unsigned long) (sp - items)) &~ 15UL)
...
165 create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
...
169 int argc = bprm->argc;
170 int envc = bprm->envc;
171 elf_addr_t __user *sp;//elf_addr_t == unsigned int
...
178 int items;
...
190 p = arch_align_stack(p);
...
287 items = (argc + 1) + (envc + 1) + 1;
288 bprm->p = STACK_ROUND(sp, items);//bprm->p = (((unsigned long) (sp - items)) &~ 15UL)
...
295 sp = (elf_addr_t __user *)bprm->p;
argc 代表传递给execve()的命令行参数个数,envc 代表传递给execve()的环境变量个数。因为argc、envc的大小都被限制在0 ~ 0x7FFFFFFF(MAX_ARG_STRINGS (fs/exec.c))之内,所以我们可以使287行的items变量整型溢出为一个负数.
因此,我们能够增加用户空间的栈指针而不是减少它(当items为负数的时候,分析第288行可知),将用户空间的栈重定向到我们的参数和环境字符串的中间,然后在SUID-root程序在用户空间执行的时候,重写这些字符串
我们执行一个 SUID-root程序,使变量items的值为0x80000000,因此需要大约0x80000000 * sizeof(char ) = 16GB的参数指针,16GB的参数字符串,16GB的环境变量字符串,但是我们的利用只需要 2 16GB = 32GB的内存,而不是 3 * 16 = 48GB,因为我们使用了一些小技巧,减少内存的使用(例如,我们用等效的文件映射替换了近16GB的相等参数指针,这些映射实际上几乎没有内存)
下面的图展示了ld.so加载我们SUID-root程序时的用户空间栈布局:
| argument strings | environment strings |
--|---|--------|---------+---------|---------+---------+---------+---------|--
| A | sprand | protect | padding | protect | scratch | onebyte | padding |
--|---|--------|---------+---------|---------+---------+------^--+---------|--
| 0-8192 ~16GB 1MB rsp ~16GB
v <-------+---|----------|
| stack | B | pointers |
\-------------->-------------->-------------->--------------/ 16GB
0x80000000 * sizeof(elf_addr_t) = 16GB
因此,ld.so调用handle_ld_preload()时,会用fname buffer(可通过LD_PRELOAD环境变量控制) 覆盖掉部分我们的onebyte区,使process_envvars()的UNSECURE_ENVVARS过滤无效(LD_AUDIT,LD_LIBRARY_PATH,LD_PRELOAD等)
利用create_elf_tables()中的整型溢出,造成UNSECURE_ENVVARS过滤无效的POC演示如下:
# gcc -O0 -o poc-suidbin poc-suidbin.c
# chown root poc-suidbin
# chmod 4555 poc-suidbin
$ gcc -o poc-exploit poc-exploit.c
$ time ./poc-exploit
...
ERROR: ld.so: object ‘LD_LIBRARY_PATH=.0LD_LIBRARY_PATH=.0LD_LIBRARY_PATH=.‘ from LD_PRELOAD cannot be preloaded:
ignored.
ERROR: ld.so: object ‘LD_LIBRARY_PATH=.0LD_LIBRARY_PATH=.‘ from LD_PRELOAD cannot be preloaded: ignored.
ERROR: ld.so: object ‘LD_LIBRARY_PATH=.‘ from LD_PRELOAD cannot be preloaded: ignored.
argc 2147090419
stack 0x7ffbe115008f < 0x7ffbe1150188 < 0x7fffe0e50128 < 0x7ff7e11503ea < 0x7ffbe102cdea
getenv 0x7ffbe114d83b .
0x7ffbe114d82b LD_LIBRARY_PATH=.
0x7ffbe114df60 LD_LIBRARY_PATH=.
0x7ffbe114df72 LD_LIBRARY_PATH=.
...
0x7ffbe114e69e LD_LIBRARY_PATH=.
0x7ffbe114e6b0 LD_LIBRARY_PATH=.
0x7ffbe114e6c2 LD_LIBRARY_PATH=.
real 5m38.666s
user 0m0.049s
sys 1m57.828s
演示程序下载地址
poc-suidbin_c.bin:
https://seclists.org/oss-sec/2018/q3/att-274/poc-suidbin_c.bin
poc-exploit_c.bin:
https://seclists.org/oss-sec/2018/q3/att-274/poc-exploit_c.bin
一共需要32GB的内存。
溢出items变量,仅仅只需要argc或envc中的任意一个就可以造成溢出,即只要argc就可以,为什么还需要16GB的环境变量呢?其实,溢出后,会造成rsp指针后移16GB,然后写入16GB的参数指针。16GB环境变量就是预留出来的存放指针的地方。
内核版本: 2.6.x, 3.10.x, 4.14.x
该漏洞至少需要32GB的内存且系统结构为x64.但是我物理机一共才24G,根本无法调试。。。。。。看来这漏洞专搞高端服务器。
CVE-2018-14634 - Linux create_elf_tables()中的整型溢出 - 翻译
标签:平台 lists .so 本地 没有 getenv 令行 eal 全栈
原文地址:https://www.cnblogs.com/r1ng0/p/9717317.html