2.3 缓冲区溢出攻击
缓冲区溢出攻击是利用缓冲区溢出漏洞所进行的攻击行动。缓冲区溢出是一种非常普遍、非常危险的漏洞,广泛存在于各种操作系统、应用软件中。利用缓冲区溢出攻击,可以导致程序运行失败、系统关机、重新启动等后果。
2.3.1 缓冲区溢出介绍
缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上。理想的情况是:程序会检查数据长度,而且并不允许输入超过缓冲区长度的字符。但是绝大多数程序都会假设数据长度总是与所分配的储存空间相匹配,这就为缓冲区溢出埋下了隐患。操作系统所使用的缓冲区,又被称为“堆栈”。在各个操作进程之间,指令会被临时储存在“堆栈”当中,“堆栈”也会出现缓冲区溢出。当一个超长的数据进入缓冲区时,超出部分就会被写入其他缓冲区,其他缓冲区存放的可能是数据、下一条指令的指针或其他程序的输出内容,这些内容都被覆盖或者破坏掉。由此可见,数据或一套指令的溢出,就可能会导致一个程序或操作系统崩溃。
黑客制造的溢出往往是有一定企图的,他们可以编写一个超过缓冲区长度的字符串植入到缓冲区,再向一个有限空间的缓冲区中植入超长的字符串,此时可能会出现以下两种结果。
① 过长的字符串覆盖了相邻的存储单元,引起程序运行失败,严重的可导致系统崩溃。
② 利用溢出漏洞可执行任意指令,甚至可取得系统root特级权限。
1.溢出根源
缓冲区溢出是由编程错误引起的。如果缓冲区被写满,而程序没有去检查缓冲区边界,也没有停止接收数据,此时就会发生缓冲区溢出。缓冲区溢出之所以泛滥,是由开放源代码程序的本质决定的。一些编程语言对于缓冲区溢出是具有免疫力的,但被广泛使用的C语言却没有建立检测机制。标准C语言具有许多复制和添加字符串的函数,这使得它很难进行边界检查。C++稍微好一些,但仍然存在缓冲区溢出。
一般情况下,覆盖其他数据区的数据是没有意义的,最多造成应用程序错误。但如果输入数据是经过“黑客”或病毒精心设计的,覆盖缓冲区数据恰恰是“黑客”或病毒的入侵程序代码,一旦多余字节被编译执行,“黑客”或病毒就有可能为所欲为,获取系统的控制权。
2.溢出原理
一个程序在内存中通常分为3部分,分别是程序段、数据段和堆栈。其中程序段放着程序的机器码和只读数据,数据段放的是程序中的静态数据,动态数据则通过堆栈来存放。它们在内存中的位置,如图所示。
内存中的程序
通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,使程序转而执行其他指令以实现入侵。造成缓冲区溢出的原因是程序中没有仔细检查用户输入的参数。例如:
void function(char *str) { char buffer[25]; strcpy(buffer, str); }
上述代码是使用strcpy()函数直接把str中的内容复制到buffer中。这样,只要str的长度大于25,就会造成buffer的溢出,使程序运行出错。存在像strcpy这样问题的标准函数还有strcat()、sprintf()、vsprintf()、gets()、scanf()等。当然,随便往缓冲区中填东西造成的溢出,一般只会出现“分段错误”(Segmentation fault),而不能实现攻击。最常见的手段是通过制造缓冲区溢出使程序运行一个用户shell,再通过shell执行其他命令。如果攻击者已经获得了一个有root权限的shell,就可以对系统进行任意操作。
2.3.2 缓冲区溢出实现攻击
黑客进行缓冲区溢出攻击的目的是扰乱具有某些特权运行的程序的功能,从而取得程序的控制权。如果该程序具有足够的权限,那么整个主机就被控制了。一般情况下,黑客利用缓冲区溢出漏洞攻击root程序,执行类似“exec(sh)”的执行代码来获得root的shell。为实现这个目的,攻击者必须达到两个目标:在程序的地址空间里安排适当的代码;通过适当地初始化寄存器和存储器,让程序跳转到事先安排的地址空间执行。
根据这两个目标,可以将缓冲区溢出攻击分为以下3类。
1.在程序的地址空间里安排适当的代码
在程序的地址空间里安排适当的代码往往比较简单,常见的方法有如下2种。
(1)植入法。
大多数情况下在所攻击的程序中是不存在攻击代码的,此时就需要使用“植入法”的方式来完成。黑客向被攻击的程序输入一个字符串,程序会把这个字符串放到缓冲区里。这个字符串包含的数据是可以在这个被攻击的硬件平台上运行的指令序列。
(2)利用已经存在的代码。
如果攻击者想要的代码已经在被攻击的程序中,攻击者所要做的只是对代码传递一些参数,然后使程序跳转到指定目标。如在C语言中,攻击代码要求执行“exec(“/bin/sh”)”。而在libc库中的代码执行“exec(arg)”,其中arg是指向一个字符串的指针参数,那么攻击者只要把传入的参数指针指向“/bin/sh”,就可以调转到libc库中相应的指令序列。
2.控制程序转移到攻击代码
该种方法是改变程序的执行流程,使之跳转到攻击代码。最基本的方法就是溢出一个没有边界检查或者其他弱点的缓冲区,从而扰乱了程序正常的执行顺序。通过溢出一个缓冲区,黑客就可以改写相邻的程序空间而直接跳过系统对身份的验证。
但由于不同地方的定位有所不同,也会产生多种转移的方式。常见的有下面3种。
(1)激活记录(Activation Records)。
这是一种比较常见的溢出方式,每当调用一个函数时,在堆栈中就会留下一个激活记录,它包含了函数结束时返回的地址。攻击者通过溢出这些自动变量,使这个返回地址指向攻击代码。通过改变程序的返回地址,当函数调用结束时,程序就会跳转到攻击者设定的地址,而不是原先的地址。
(2)函数指针(Function Pointers)。
在C语言中,“void(* foo)()”声明了一个返回值为void函数指针的变量foo。函数指针可以用来定位任何地址空间,所以攻击者只需在任何空间内的函数指针附近找到一个能够溢出的缓冲区,然后就可溢出这个缓冲区来改变函数指针。在某一时刻,当程序通过函数指针调用函数时,程序的流程就按攻击者的意图实现。
(3)长跳转缓冲区(Longjmp buffers)。
在C语言中包含了一个简单的检验/恢复系统,即setjmp/longjmp。其作用是在检验点设定“setjmp(buffer)”,而用“longjmp(buffer)”来恢复检验点。但是如果攻击者能够进入缓冲区的空间,“longjmp(buffer)”实际是跳转到攻击者的代码。和函数指针一样,longjmp缓冲区能够指向任何地方,所以攻击者所要做的就是找到一个可供溢出的缓冲区。
3.综合代码植入和流程控制技术
在进行溢出缓冲区攻击时,常常需要在一个字符串里综合代码植入和激活记录。攻击者需要定位一个可供溢出的自动变量,然后向程序传递一个很大的字符串,在引发缓冲区溢出改变激活记录的同时植入了代码。代码植入和缓冲区溢出不一定要在一次动作中完成。攻击者可以在一个缓冲区内放置代码,这时不能溢出缓冲区。然后,攻击者通过溢出另一个缓冲区来转移程序的指针。这种方法一般用来解决可供溢出的缓冲区不够大的问题。
如果攻击者想使用已经驻留的代码而不是从外部植入代码,就必须先把代码参数化。如在libc中的部分代码段会执行“exec(some)”,其中some就是参数。攻击者使用缓冲区溢出改变程序的参数,再利用另一个缓冲区溢出使程序指针指向libc中特定的代码段。
2.3.3 如何防范缓冲区溢出攻击
由于缓冲区溢出攻击可以带来恶劣的后果,所以要采取措施对缓冲区溢出攻击进行防御。目前有如下几种方法可以保护缓冲区免受缓冲区溢出的攻击和影响。
1.编写正确的代码
编写正确的代码是一项非常有意义但耗时的工作,特别是像编写C语言那种具有容易出错倾向的程序。尽管花了很长的时间使得人们知道了如何编写安全的程序,但具有安全漏洞的程序依旧出现。因此,需要开发一些工具和技术来帮助经验不足的程序员编写安全正确的程序。
2.非执行的缓冲区
通过使被攻击程序的数据段地址空间不可执行,从而使得攻击者不可能执行植入被攻击程序输入缓冲区的代码,这种技术被称为非执行的缓冲区技术。但Windows系统为了实现更好的性能和功能,往往在数据段中动态地放入可执行的代码。为了保持程序的兼容性,不可能使所有程序的数据段不可执行,所以缓冲区漏洞是存在的。
3.数组边界检查
该种方式和非执行缓冲区的不同在于:数组边界检查完全放置了缓冲区溢出的产生和攻击。所以只要数组不能被溢出,溢出攻击也就无从谈起。为了实现数组边界检查,所有对数组的读写操作都应该被检查,以确保对数组的操作在正确的范围内。最直接的方法是检查所有的数组操作,但是通常可以采用一些优化的技术来减少检查的次数。
4.程序指针完整性检查
程序指针完整性检查和数组边界检查略微不同:程序指针完整性检查可在程序指针被引用之前检测到它的改变。即使一个攻击者成功地改变了程序的指针,由于系统事先检测到了指针的改变,这个指针也将不会被使用。
程序指针完整性检查不能解决所有的缓冲区溢出问题;但是这种方法在性能上有很大的优势,而且兼容性也很好。
2.3.4 IIS.printer攻击案例
缓冲区溢出攻击是远程网络攻击中最常见的一种攻击方式,可以使得一个匿名的Internet用户有机会获得一台主机的部分或全部控制权。如果能有效地消除缓冲区溢出的漏洞,则很大一部分的安全威胁可以得到缓解。
IIS.printer漏洞(应用程序映射缓冲溢出)是比较流行的漏洞,国内及国外仍有很多台计算机存在此漏洞。该漏洞只存在于运行IIS 5.0服务器中。由于IIS 5打印ISAPI扩展接口建立了.printer扩展名到Msw3prt.dll的映射关系(缺省情况下该映射也存在)。
当远程用户提交对.printer的URL请求时,IIS 5.0会调用Msw3prt.dll文件来解释该请求,但Msw3prt.dll缺乏足够的缓冲区边界检查。如果黑客提交一个精心构造的针对.printer的URL请求,且其“Host:”域包含大约420B的数据,此时在Msw3prt.dll中会发生典型的缓冲区溢出。在溢出发生之后,Web服务将会停止用户响应,而计算机就会自动重启,这样系统管理员就很难检查到已发生的攻击。
2.3.5 RPC缓冲区溢出攻击案例
Microsoft的RPC(Remote Procedure Call,远程过程调用)部分在通过TCP/IP处理信息交换时会出现漏洞,该漏洞是由于不正确处理畸形信息所致,会影响使用RPC的DCOM接口。该接口处理由客户端计算机发送给服务器的DCOM对象激活请求。攻击者成功利用该漏洞,可以在本地系统权限执行安装程序、查看、更改、建立系统管理员权限的账户及删除数据等。
注意
分布式对象(DCOM)是一种可以使软件组件通过网络直接进行网络通信的协议,可以跨越包括Internet协议(例如HTTP)在内的多种网络传输。
(1)漏洞检测。
检测这类漏洞使用RPC漏洞专用扫描器Retina(R)-DCOM Scanner。它是eEye安全公司针对微软MS03-026以及最新MS03-039 RPC DCOM漏洞的扫描工具。
使用该软件扫描RPC漏洞的具体操作步骤如下。
1运行Retina(R)-DCOM Scanner主程序,即可打开“Retina(R)-DCOM Scanner”主窗口,在“Start IP”文本框和“End IP”文本框中分别输入起始和终止的IP地址,如图所示。
“Retina(R)-DCOM Scanner”主窗口
2单击“Scan”按钮,即可开始扫描,如图所示。如果在设置的IP范围中有存在RPC漏洞的主机,则该主机的详细信息将出现在扫描结果中。
设置扫描的IP范围
(2)漏洞利用。
RPC溢出漏洞带来的危害很严重,比如基于RPC漏洞的著名病毒“冲击波”,可导致目标计算机反复重启系统,不能正常复制文件和浏览网站,同时DNS、IIS、路由器等受到非法拒绝服务攻击,甚至整个网络系统处于瘫痪状态。
漏洞利用工具有两个:Rpcdcom和OpenRpcss。先使用Rpcdcom对远程主机发送畸形数据包,再使用OpenRpcss攻击远程主机,最终会在远程主机内部建立一个管理员账号。
其中Rpcdcom命令格式:Rpcdcom Server。
OpenRpcss命令格式:OpenRpcss \\Server。
使用这两种工具入侵存在RPC漏洞的主机的具体步骤如下。
1先使用“Rpcdcom存在漏洞远程主机的IP地址”命令给远程主机发送畸形数据。
2使用“OpenRpcss.exe\\存在漏洞远程主机的IP地址”命令在该远程主机中建立管理员账号。
3在远程主机内部成功建立一个管理员账号后,使用“net use \\存在漏洞远程主机的IP地址\IPC$ "密码"/user:"用户名"”命令,即可通过IPC$管道连接证明管理员账号是否创建成功。
(3)漏洞的防范。
黑客可以利用RPC漏洞给远程服务器监听的特定RPC端口发送畸形请求,如135、139、445等任何配置了RPC端口的计算机在受到攻击时,Windows系统都出现蓝屏、重启以及自动关机的现象。下面有两种方法可很好地预防RPC漏洞攻击。
更改RPC服务设置。在Windows系统中可以通过设置相关的服务来预防RPC缓冲区溢出攻击,具体操作步骤如下。
1在“管理工具”窗口中双击“服务”图标,即可打开“服务”窗口,在其中可以看到本机中所有的服务,如图所示。在“服务”列表中右击“Remote Proceduce Call(RPC)”服务,在快捷菜单中选择“属性”选项,即可打开“Remote Proceduce Call(RPC)的属性(本地计算机)”对话框。
“服务”窗口
2切换到“恢复”选项卡,将其中的第一、二次失败以及后续失败都设置为“无操作”选项,如图所示。
“Remote Procedure Call(RPC)的属性”对话框
2.3.6 即插即用功能远程控制缓冲区溢出漏洞
UPnP(Universal Plug and Play,通用即插即用)是一种用于PC机和智能设备(或仪器)的常见对等网络连接的体系结构,尤其是在家庭中。它允许不同的设备(如计算机、扫描仪、打印机等)连接网络,从而可以在彼此之间自动识别并进行通信。这样,用户就不需要为每个外设来配置计算机。
但UPnP对缓冲区(Buffer)的使用没有进行检查和限制,黑客可利用这一漏洞控制同一网络上的计算机或发动D.o.S攻击。更为严重的是,同一网络的其他用户甚至不需要知道该计算机的IP地址,就可以对其发动攻击。这个缺陷导致的后果很严重,不论哪个版本的Windows系统,只要运行UPnP,就都存在这个危险。
但严格地说,这并不完全是UPnP技术本身的问题,更多的是程序设计的疏忽。UPnP协议存在安全漏洞问题,是由eEye数字安全公司最早发现并通知微软的。其中的UPnP缓冲区溢出,是Windows中有史以来最严重的缓冲溢出漏洞。
(1)漏洞检测。
可以使用MS05-039Scan工具检测此类漏洞,它是一款用于Microsoft Windows即插即用功能远程缓冲区溢出漏洞的专用扫描工具。
只检测出远程主机存在的漏洞远远不够,还需要使用X-Scan来对远程主机进行扫描,以得到远程主机上使用的Windows操作系统类型等信息。
(2)漏洞利用。
如果检测到UPnP缓冲区溢出漏洞,则可以利用专门的工具对目标计算机进行攻击。在入侵过程中使用的工具是ms05039.exe,其命令格式为:ms05039.exe<host><conIP><conP ort>[target]。各个参数的含义如下。
· host:指远程主机IP地址或远程主机名。
· conIP:本地IP地址。
· ConPort:溢出成功后远程主机的端口号。
· Target:选择操作系统类型。