缓冲区溢出深度防御体系

 
谈及防御之前
------------
首先简要回顾一下缓冲区溢出的攻击大系:

栈溢出( stack smashing
未检查输入缓冲区长度,导致数组越界,覆盖栈中局部变量空间之上的栈桢指针 %ebp 以及函数返回地址 retaddr,
当函数返回执行 ret 指令时, retaddr 从栈中弹出,作为下一条指令的地址赋给 %eip 寄存器,继而改变原程序的执
行流程指向我们的 shellcode.

堆溢出( malloc/free heap corruption
一种是和传统的栈溢出一样 , 当输入超出 malloc() 预先分配的空间大小,就会覆盖掉这段空间之后的一段存储区域,
如果该存储区域有一个重要的变量比如 euid ,那么我就可以用它来攻击。另一种是典型的 double-free 堆腐败,在
内存回收操作中,合并相邻空闲块重新插入双向链表时会有一个写 4 字节内存的操作,如果弱点程序由于编程错误
free()
一个不存在的块,我们就可以精心伪造这个块,从而覆盖任何我们想要的值:函数的返回地址、库函数的
.plt
地址等

格式化字符窜漏洞( format string vulnerability
如果格式窜由用户定制,攻击者就可以任意伪造格式窜,利用 *printf() 系列函数的特性就可以窥探堆栈空间的内
容,超常输入可以引发传统的缓冲区溢出,或是用 ”%n” 覆盖指针、返回地址等。

整形变量溢出( integer variable overflow
利用整数的范围、符号等问题触发安全漏洞,大多数整形溢出不能直接利用,但如果该整形变量决定内存
分配等操作,我们就有可能间接利用该漏洞。

其他的攻击手法( others
只能算是手法,不能算是一种单独的类别。利用 ELF 文件格式的特性如:覆盖 .plt (过程连接表)、 .dtor
(析构函数指针)、 .got (全局偏移表)、 return-to-libc (返回库函数)等的方式进行攻击。

----------------
一、编译保护技术
----------------
Stackguard
因为缓冲区溢出的通常都会改写函数返回地址, stackguard 是个编译器补丁,它产生一个" canary "值 ( 一个
单字 ) 放到返回地址的前面,如果当函数返回时,发现这个 canary 的值被改变了,就证明可能有人正在试图进行缓冲区
溢出攻击,程序会立刻响应,发送一条入侵警告消息给 syslogd, 然后终止进程。" canary "包含: NULL 0x00 ), CR
0x0d ), LF 0x0a EOF 0xff )四个字 符,它们应该可以阻止大部分的字符串操作,使溢出攻击无效。一
个随机数 canary 在程序执行的时候被产生。所以攻击者不能通过搜索程序的二进制文件得到" canary "值。如果 /dev/
urandom
存在,随机数就从那里取得。否则,就从通过对当前时间进行编码得到。其随机性足以阻止绝大部分的预测攻
击。 Immunix 系统为采用 stackguard 编译的 Red Hat Linux, stackguard 所提供的保护并非绝对安全,满足一些条件就
可以突破限制:如覆盖一个函数指针、可能存在的 exit() _exit() 系统调用地址、 GOT 等。
Stackguard
官方链接:
http://immunix.org/

Stackshield
StackShield
使用了另外一种不同的技术。它的做法是创建一个特别的堆栈用来储存函数返回地址的一份拷贝。
它在受保护的函数的开头和结尾分别增加一段代码,开头处的代码用来将函数返回地址拷贝到一个特殊的表中,而结尾
处的代码用来将返回地址从表中拷贝回堆栈。因此函数执行流程不会改变,将总是正确返回到主调函数中。在新的版本
中已经增加了一些新的保护措施,当调用一个地址在非文本段内的函数指针时,将终止函数的执行。
Stackshield
无法防御只覆盖 %ebp 的单字节溢出,同样,我们也可以通过覆盖其他的 ELF 结构来绕过限制。
www.angelfire.com/sk/stackshield/download.html

------------------
二、库函数链接保护
------------------
Formatguard
Formatguard
是个 Glibc 的补丁,遵循 GPL ,它使用特殊的 CPP gcc 预编译程序)宏取代原有的 *printf() 的参数
统计方式,它会比较传递给 *printf 的参数的个数和格式窜的个数,如果格式窜的个数大于实际参数的个数,就判定为
攻击行为,向 syslogd 发送消息并终止进程。如果弱点程序调用 Glibc 以外的库, formatguard 就无法保护。
www.immunix.org

Libsafe
Libsafe
是一个动态链接库,在标准的 C 库之前被加载,主要加固了 gets() strcpy() strcat() sprintf()……
等容易发生安全问题的 C 函数,它设计为只针对 stack smashing && format string 类型的攻击。 Alert7 很早也写过如何
绕过 libsafe 保护的文章。
http://www.research.avayalabs.com/project/libsafe/

--------------
三、栈不可执行
--------------
Solar designer’s nonexec kernel patch
从名字可以看出这是一个 Linux 上的内核补丁,该补丁最主要的特性是:用户区堆栈不可执行 [Non-executable User Stack]
由于 x86 CPU 上并没有提供页( page )执行的 bit 位,所以该补丁通过减小代码段的虚拟地址来区分数据段和代码
段,程序执行流返回 0xC0000000 以下一段用户堆栈空间的操作都被认为是缓冲区溢出攻击行为,随即产生一个通用保护异
常而终止进程。这样把 shellcode 安置在 buffer 或环境变量(都位于堆栈段)的 exploit 都会失效。当然其安全也不是绝对的,
利用 PLT 返回库函数的文章里详细描述了突破该补丁的攻击方法。
该补还有一些其他的特性:动态链接库映射到地址低端( 0x00 开始)、限制符号链接攻击、 /tmp 目录限制、 /proc
录限制、 execve 系统调用加固等。
www.openwall.com

Solaris/SPARC nonexec- stack protection
Solaris/SPARC 下可以通过去掉堆栈的执行权限来禁止堆栈段执行,方法如下,在 /etc/system 中加入两条语句:
Set noexec_user_stack = 1
Set noexec_user_stack_log = 1
第一条禁止堆栈执行,第二条记录所有尝试在堆栈段运行代码的活动。 Reboot 之后才会生效。
所有只让栈不可执行的保护是有限的。 Return-to-libc fake frame 之类的技术都可以突破限制,不过栈不可执行的保护已经
极大了提升了攻击难度。

------------------
四、数据段不可执行
------------------
kNoX
Linux
内核补丁,功能:数据段的页不可执行,撤销共享内存,加强对 execve 系统调用的限制,对文件描述符 0 1 2
特殊处理, /proc 目录的限制, FIFO 限制,符号链接限制,该补丁只支 2.2 内核。
http://isec.pl/projects/knox/knox.html

RSX
Linux
内核模块,数据段( stack heap )不可执行。
http://www.starzetz.com/software/rsx/

Exec shield
Exec-shield
从内核态显示的跟踪一个应用程序所包含的可执行映像的最大虚拟地址,动态的维护这个 可执行虚拟地址
的最大值 称为 可执行限界 ,每次发生进程切换的时候调度进程就会用这个值更新代码段描述符写入 GDT exec-shield 动态
的跟踪每个应用程序,所以每个程序运行时都有不同的 可执行限界 ,因为可执行限界通常是个很低的虚拟地址,所以除了
stack
以外 mmap() 映射的区域以及 malloc() 分配的空间都处在可执行限界之上,因此都是不可执行的。
当然 Exec-shield 无法防御跳转到低 16M 地址空间和 return-to-libc 的攻击,不过还是能阻止绝大多数把 shellcode 安置在
数据段的攻击。

http://redhat.com/~mingo/exec-shield/

---------------------------------
五、增强的缓冲区溢出保护及内核 MAC
---------------------------------
OpenBSD security feature
OpenBSD
Hardened Gentoo Adamantix SELinux 都是属于默认安全等级非常高的操作系统。 OpenBSD 经过代码审计,
漏洞非常少。同样他具有很多安全特性:
*
使用 strlcpy() strlcat() 函数替换原有的危险函数
*
内存保护: W^X 、只读数据段、页保护、 mmap() 随机映射、 malloc() 随机映射、 atexit() stdio 保护、
*
特权分离
*
特权回收
*BSD chroot jail
*
其他的很多特性
其中 W^X 有不少内容: stack mmap 随机映射,只读 GOT/PLT/.ctor/.dtor 等。虽然理论上 OpenBSD 无法阻止所有类型的攻击,
但已经阻断了不少攻击手法。

PaX
PaX
是个非常 BT 的东西,好像天生就是缓冲区溢出的死对头,他严厉的审视每一种攻击方式,予以阻断。
*
基于 x86 段式内存管理的数据段不可执行
*
基于页式内存管理的数据段的页不可执行
*
内核页只读 {
-Const
结构只读
-
系统调用表只读
-
局部段描述符表( IDT )只读
-
全局段描述符表( GDT )只读
-
数据页只读
-
该特性不能与正常的 LKM 功能共存 }
*
完全的地址空间随机映射 {
-
每个系统调用的内核栈随机映射
-
用户栈随机映射
-ELF
可执行映像随机映射
-Brk()
分配的 heap 随机映射
-Mmap()
管理的 heap 随机映射
-
动态链接库随机映射 }
*
还有诸如把动态链接库映射到 0x00 开始的低地址的其他特性
这里顺便提一下 Phrack58 Nergal 写过的 <<The advanced return-into-lib(c) exploits >> ,这篇大作里提到用伪造栈桢
Fakeframe )和 dl-resolve() 技术突破 PaX 若干保护的方法,这极有可能 *nix 应用层 exploit 技术中最高级的技术, Nergal
解决了几个问题: Stack/Heap/BSS 不可执行、 mmap 随机映射,显然这种高级的技术仍然无法无条件的突破 PaX ,所以在一个
运行完全版 PaX Linux 上,你想发动缓冲区溢出可能是没有机会的!!!
PaX Team
http://pax.grsecurity.net

Grsecurity
Grsec
内含 PaX( 这个更 BT ??汗 ~) ,和 Lids 一样 grsec 支持内核 MAC Madatory Access Control ,强制访问控制),
拥有非常多的特性 , 详见 http://grsecurity.net/features.php
www.grsecurity.net

------------------
六、硬件级别的保护
------------------
X86 CPU
上采用 4GB 平坦模式,数据段和代码段的线性地址是重叠的,页面只要可读就可以执行,所以上面提到的诸多
内核补丁才会费尽心机设计了各种方法来使数据段不可执行。现在 Alpha PPC PA-RISC SPARC SPARC64 AMD64 IA64 都提
供了页执行 bit 位。 Intel AMD 新增加的页执行比特位称为 NX 安全技术, Windows XP SP2 Linux Kernel 2.6 都支持 NX ,虽然
这种硬件级的页保护不如 PaX 那样强,但硬件级别的支持无疑大大增加了软件和操作系统的兼容性,能够使缓冲区溢出的防护
得到普及。

----------
Conclusion
----------
安全和易用性总是站在对立面上,以上提及的保护技术都会引起少量的性能损耗,设计者们已经从性能的角度优化了
他们的作品。然而人们更关心的问题是兼容性,也许你会发现在那些运营级的 BOX 上根本看不到这些东西,是的,人们希望的
另一种安全是不发生错误,即稳定的运行,使用这些额外的保护会给人造成心理不安,我相信随着 NX 的流行以及保护技术本身
的发展这些问题都会得到解决。也许你经常会看到这样或那样的文章讲述如何突破缓冲区溢出保护的高级 exploit 技术,其实
很多内容只适合作为教学、或者技术本身还处在研究阶段,在实际的攻击中,使用高级的 bypass 技术通常需要满足一些条件,
并不是单纯多花点力气增长了 exploit 代码的长度就能达到目的,在使用缓冲区溢出保护的系统上,攻击将变得非常困难,有些
时候其实就是不可能,尤其是在远程无法精确得到必须的 ELF 符号地址的时候,很多技术都将变成纸上谈兵。
使用类似 PaX 的补丁, +iptables 规则 , 再结合内核 MAC, 想入侵得到 shell 几乎是不可能的,可惜偶没钱,不然拿个 Linux box
放到 Internet 上公测,让牛人们尽兴的玩玩,哈 ~
在缓冲区溢出尚未成为历史的今天,暂且缅怀一下吧,这当然也不是什么悲观的论调,旧技术的消亡必然伴随着新技术
的诞生,如果没有了 Evil Hacking 我们还坐在电脑前干什么呢?如果那样的话,我就和傻 Billy 去开个小超市,顺便告诉 Adam Why
他们也别干了。。让那些做安全啥也不懂就会吹牛的人去干吧 ~~

PST

Ph4nt0m Security Team
http://www.ph4nt0m.org
一群无拘无束的年轻人,虽然大多从事网络安全工作,却因为崇尚 Black Hat 而聚到一起。
 

你可能感兴趣的:(linux,String,Security,user,Integer,internet)