CVE-2010-3192 漏洞分析

最近几天本来是在做Pwn题目,做到了smash-the-stack这道题目。

这道题开了Canary,经我IDA查看,没发现什么利用点。
我查询这道题目的WP[1],发现这个题目的原理如下[2]:

假设程序中只存在线性写入栈区域的函数(例如scanf, write)。如果攻击者想要改变控制流(返回地址),就必须要覆盖Canary的值。程序控制流在发生ret转移之前会先对Canary进行检查,如果Canary比较不一致就会转入动态链接,位于libc中的__stack_chk_fail函数进行执行。输出的内容如下图。

发现了什么吗?输出的东西出现了程序的名字!我们应该对这个东西有点敏感性,这个玩意是啥呢?他就是argv[0]!为了验证这个猜想,我们来看下面__stack_chk_fail的源代码:

调用了__fortify_fail函数,我们再来看__fortify_fail的源代码:

我们发现,它确实输出了argv[0]的内容。看到这里,对于体系结构、操作系统、编译系统了解较多的同学应该就知道怎么利用这个漏洞了,如果还不清楚,可以看下面这张图,了解一下Linux的栈布局。

首先,栈是由高地址向低地址增长的。对于每一次函数的调用,相应的,在栈中都会分配出一块区域,用于在函数执行过程中存储临时数据。我们把它叫做栈帧(Stack Frame)或活动记录(Active Record)。

为简便起见,下面以开启Canary的i386体系结构举例。
对于一般的函数栈帧,由高地址向低地址,布局的内容分别为:函数实参(Function Arguments)、返回地址(Return Address)、旧帧指针(Old %ebp)、其他保存寄存器(Saved Registers)、Canary值、自动变量(Auto Variable)。

这些应该是比较常见的关于栈布局的内容。但是,描述栈布局的教程很多都没有说:argc/argv/environ这些由用户传入的参数,怎么被操作系统布局在程序的栈空间中?
它们其实被布局在栈的最底部,也就是说,布局在栈的最高地址。

所以,只要允许输入的长度足够长,不管你调用了多少层函数,整个线程的栈都会被你的输入所覆盖,自然也就能覆盖到argv[0]。你可以通过精心构造,覆盖argv[0]为任意内存地址,当Canary被破坏时,调用__stack_chk_fail就会输出argv[0]指针所对应的内容,造成任意内存地址泄漏。

这就是这个漏洞的原理。本来如果到此,PoC能直接在我机器上运行成功,peda-gdb调试没问题,应该也就没有这篇文章了[捂脸]。

但在我新版Ubuntu 20.04机器上进行实际测试时,发现即使没有破坏argv[0]的内容,也只会输出<Unknown>,而不会输出程序的名字;而连接CTF的Pwn目标机,WP给出的PoC则是可行的。因此我怀疑,这个漏洞可能已经在新版本libc中被修复。

为了探究清楚这个问题,我决定去看一番最新版libc的源代码。

首先看__stack_chk_fail [3]:

好家伙,发现最新版的它变了。

再跟进去看__fortify_fail_abort [4]:

一看逻辑,清清楚楚,直接输出<unknown>。上面注释还说的很明白,为了防止输出损坏的栈,就不打印argv[0]了。[捂脸]

再搜搜,好家伙,发现这个洞已经是个CVE了,还是2010年的[6][7][8][9]。因此我决定写个文章纪念一下我第一次分析CVE[捂脸],所以就有了这篇文章。

根据[9],这个洞是在libc 2.26中被修复的。我把glibc 2.23和2.27的源码下载并对比了一下。确实发现2.23有洞,2.27没洞。截图如下。


有洞的2.23


没洞的2.27

综上,得到两个经验:
1、你发现的Bug可能人家早就修了
2、没事干要好好读libc,说不定我早出生20年,CVE编号就全归我了(逃

参考资料:
[1] https://blog.csdn.net/niexinming/article/details/78522682
[2] https://j00ru.vexillium.org/slides/2015/insomnihack.pdf
[3] https://code.woboq.org/userspace/glibc/debug/stack_chk_fail.c.html
[4] https://code.woboq.org/userspace/glibc/debug/fortify_fail.c.html
[5] https://lbarman.ch/blog/stack_smashing/
[6] https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/562614
[7] https://cve.mitre.org/cgi-bin/cvename.cgi?name=2010-3192
[8] https://seclists.org/fulldisclosure/2010/Apr/399
[9] https://nvd.nist.gov/vuln/detail/CVE-2010-3192

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注