如何处理Android中的防缓冲区溢出技术
【51CTO专稿】本文将具体介绍Android中的防缓冲区溢出技术的来龙去脉。
1、什么是ASLR?
ASLR(Address space layout randomization)是一种针对缓冲区溢出的安全保护技术,通过对堆、栈、共享库映射等线性区布局的随机化。通过添加攻击者预測目的地址的难度。防止攻击者直接定位攻击代码位置,达到阻止溢出攻击的目的。通常情况下。黑客会利用某个特定函数或库驻存在特定内存位置的这一事实。通过在操纵堆或其它内存错误时调用该函数来发动攻击。ASLR则可以避免这样的情况。由于它能确保系统和应用程序的代码每次被载入时不会出如今同一个存储位置。
苹果的iOS系统自iOS 4.3以后就支持ASLR技术;尽管Comex在7月份公布的“iPhone越狱”软件就已攻克这一防御措施。而Android已经在4.0中应用了ASLR技术。
据研究表明ASLR能够有效的减少缓冲区溢出攻击的成功率,现在Linux、FreeBSD、Windows等主流操作系统都已採用了该技术。
2、缓冲区溢出攻击原理
缓冲区溢出是一种很普遍、很危急的漏洞。在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,能够导致程序执行失败、系统宕机、又一次启动等后果。
更为严重的是。能够利用它执行非授权指令。甚至能够取得系统特权。进而进行各种非法操作。
缓冲区溢出(图1)是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量溢出的数据覆盖在合法数据上,理想的情况是程序检查数据长度并不同意输入超过缓冲区长度的字符,可是绝大多数程序都会如果数据长度总是与所分配的储存空间相匹配,这就为缓冲区溢出埋下隐患.操作系统所使用的缓冲区 又被称为"堆栈". 在各个操作进程之间,指令会被暂时储存在"堆栈"其中,"堆栈"也会出现缓冲区溢出。
在当前网络与分布式系统安全中,被广泛利用的50%以上都是缓冲区溢出,当中最著名的样例是1988年利用fingerd漏洞的蠕虫。
而缓冲区溢出中,最为危急的是堆栈溢出,由于入侵者能够利用堆栈溢出。在函数返回时改变返回程序的地址。让其跳转到随意地址,带来的危害一种是程序崩溃导致拒绝服务,第二种就是跳转而且运行一段恶意代码,比方得到shell,然后为所欲为。
历史上最著名的缓冲区溢出攻击可能要算是1988年11月2日的Morris Worm所携带的攻击代码了。
这个因特网蠕虫利用了fingerd程序的缓冲区溢出漏洞,给用户带来了非常大危害。此后,越来越多的缓冲区溢出漏洞被发现。从bind、wu-ftpd、telnetd、apache等经常使用服务程序,到Microsoft、Oracle等软件厂商提供的应用程序,都存在着似乎永远也弥补不完的缓冲区溢出漏洞。
图1 缓冲区溢出攻击示意
3、应用ASLR后的一个简单对照样例
以下使用一个比較典型的样例来显示使用ASLR前后的效果:
C源码:
- #include <stdlib.h>
- #include <unistd.h>
- main()
- {
- char *i;
- char buff[20];
- i=malloc(20);
- sleep(1000);
- free(i);
- }
- #ps -aux|grep test
- Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
- aslr_test 8731 0.0 0.0 1632 332 pts/0 S+ 18:49 0:00 ./test
- aslr_test 8766 0.0 0.0 2884 748 pts/1 R+ 18:49 0:00 grep test
- aslr_test@aslr_test-laptop:~$ cat /proc/8731/maps
- 08048000-08049000 r-xp 00000000 08:01 2256782 /home/aslr_test/Desktop/test
- 08049000-0804a000 rw-p 00000000 08:01 2256782 /home/aslr_test/Desktop/test
- 0804a000-0806b000 rw-p 0804a000 00:00 0 [heap]
- b7e60000-b7e61000 rw-p b7e60000 00:00 0
- b7e61000-b7f9c000 r-xp 00000000 08:01 12116 /lib/tls/i686/cmov/libc-2.5.so
- b7f9c000-b7f9d000 r--p 0013b000 08:01 12116 /lib/tls/i686/cmov/libc-2.5.so
- b7f9d000-b7f9f000 rw-p 0013c000 08:01 12116 /lib/tls/i686/cmov/libc-2.5.so
- b7f9f000-b7fa2000 rw-p b7f9f000 00:00 0
- b7fae000-b7fb0000 rw-p b7fae000 00:00 0
- b7fb0000-b7fc9000 r-xp 00000000 08:01 12195 /lib/ld-2.5.so
- b7fc9000-b7fcb000 rw-p 00019000 08:01 12195 /lib/ld-2.5.so
- bfe86000-bfe9c000 rw-p bfe86000 00:00 0 [stack]
- ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
- #ps -aux|grep test
- Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
- aslr_test 8781 0.0 0.0 1632 332 pts/0 S+ 18:49 0:00 ./test
- aslr_test 8785 0.0 0.0 2884 748 pts/1 R+ 18:49 0:00 grep test
- aslr_test@aslr_test-laptop:~$ cat /proc/8781/maps
- 08048000-08049000 r-xp 00000000 08:01 2256782 /home/aslr_test/Desktop/test
- 08049000-0804a000 rw-p 00000000 08:01 2256782 /home/aslr_test/Desktop/test
- 0804a000-0806b000 rw-p 0804a000 00:00 0 [heap]
- b7e1e000-b7e1f000 rw-p b7e1e000 00:00 0
- b7e1f000-b7f5a000 r-xp 00000000 08:01 12116 /lib/tls/i686/cmov/libc-2.5.so
- b7f5a000-b7f5b000 r--p 0013b000 08:01 12116 /lib/tls/i686/cmov/libc-2.5.so
- b7f5b000-b7f5d000 rw-p 0013c000 08:01 12116 /lib/tls/i686/cmov/libc-2.5.so
- b7f5d000-b7f60000 rw-p b7f5d000 00:00 0
- b7f6c000-b7f6e000 rw-p b7f6c000 00:00 0
- b7f6e000-b7f87000 r-xp 00000000 08:01 12195 /lib/ld-2.5.so
- b7f87000-b7f89000 rw-p 00019000 08:01 12195 /lib/ld-2.5.so
- bfe23000-bfe39000 rw-p bfe23000 00:00 0 [stack]
- ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
通过两次执行后对照/proc下的进程信息可以发现进程栈和共享库映射的地址空间都有了较大的变化。这使得以往通过esp值来推測shellcode地址的成功率大大减少了。Phrack59期有一篇文章介绍过使用return-into-libc的方法突破ASLR保护。只是存在着较大的条件限制。milw0rm的一篇文章也介绍了通过搜索linux-gate.so.1中的jmp %esp指令从而转向执行shellcode的方法,只是因为如今的编译器将要恢复的esp值保存在栈中,因此也不能继续使用。总的来说,ASLR技术可以非常好地保证Android代码及执行安全。