缓冲区溢出原理及防范

合集下载

第7章缓冲区溢出攻击及防御技术ppt课件

第7章缓冲区溢出攻击及防御技术ppt课件

2024/3/29
网络入侵与防范技术
7
篮球比赛是根据运动队在规定的比赛 时间里 得分多 少来决 定胜负 的,因 此,篮 球比赛 的计时 计分系 统是一 种得分 类型的 系统
7.1 缓冲区溢出概述
隐蔽性:
第三,由于漏洞存在于防火墙内部的主机上,攻击者可 以在防火墙内部堂而皇之地取得本来不被允许或没有权 限的控制权;
2024/3/29
网络入侵与防范技术
1
篮球比赛是根据运动队在规定的比赛 时间里 得分多 少来决 定胜负 的,因 此,篮 球比赛 的计时 计分系 统是一 种得分 类型的 系统
7.1 缓冲区溢出概述
什么是缓冲区?它是包含相同数据类型实例的一个 连续的计算机内存块。是程序运行期间在内存中分 配的一个连续的区域,用于保存包括字符数组在内 的各种数据类型。
Windows系统中缓冲区溢出的事例更是层出不穷。 2001年“红色代码”蠕虫利用微软IIS Web Server中
的缓冲区溢出漏洞使300 000多台计算机受到攻击; 2003年1月,Slammer蠕虫爆发,利用的是微软SQL
Server 2000中的缺陷; 2004年5月爆发的“振荡波”利用了Windows系统的活
产生碎片不同 对堆来说,频繁的new/delete或者malloc/free势必会造成 内存空间的不连续,造成大量的碎片,使程序效率降低。 对栈而言,则不存在碎片问题,因为栈是先进后出的队列, 永远不可能有一个内存块从栈中间弹出。
生长方向不同 堆是向着内存地址增加的方向增长的,从内存的低地址向高 地址方向增长。 栈的生长方向与之相反,是向着内存地址减小的方向增长, 由内存的高地址向低地址方向增长。
1999年w00w00安全小组的Matt Conover写了基于 堆缓冲区溢出专著,对堆溢出的机理进行了探索。

缓冲区溢出原因及解决

缓冲区溢出原因及解决

第三讲缓冲区溢出n1 缓冲区溢出问题简介n2 几种典型的缓冲区溢出n3 防范措施缓冲区溢出1 缓冲区溢出问题简介缓冲区溢出是一种常见的漏洞.据统计,通过缓冲区溢出进行的攻击占所有系统攻击总数的80%以上.这种错误的状态发生在写入内存的数据超过了分配给缓冲区的大小的时候,就像一个杯子只能盛一定量的水,如果放到杯子中的水太多,多余的水就会一出到别的地方。

由于缓冲区溢出,相邻的内存地址空间被覆盖,造成软件出错或崩溃。

如果没有采取限制措施,可以使用精心设计的输入数据使缓冲区溢出,从而导致安全问题。

缓冲区溢出缓冲区溢出问题的历史很长一段时间以来,缓冲区溢出都是一个众所周知的安全问题, C程序的缓冲区溢出问题早在70年代初就被认为是C语言数据完整性模型的一个可能的后果。

这是因为在初始化、拷贝或移动数据时,C语言并不自动地支持内在的数组边界检查。

虽然这提高了语言的执行效率,但其带来的影响及后果却是深远和严重的。

•1988年Robert T. Morris的finger蠕虫程序.这种缓冲区溢出的问题使得Internet几乎限于停滞,许多系统管理员都将他们的网络断开,来处理所遇到的问题. •1989年Spafford提交了一份关于运行在VAX机上的BSD版UNIX的fingerd的缓冲区溢出程序的技术细节的分析报告,引起了部分安全人士对这个研究领域的重视•1996年出现了真正有教育意义的第一篇文章, Aleph One在Underground发表的论文详细描述了Linux系统中栈的结构和如何利用基于栈的缓冲区溢出。

缓冲区溢出Aleph One的贡献还在于给出了如何写开一个shell的Exploit的方法,并给这段代码赋予shellcode的名称,而这个称呼沿用至今,我们现在对这样的方法耳熟能详--编译一段使用系统调用的简单的C程序,通过调试器抽取汇编代码,并根据需要修改这段汇编代码。

•1997年Smith综合以前的文章,提供了如何在各种Unix变种中写缓冲区溢出Exploit更详细的指导原则。

缓冲区溢出攻击原理与防范

缓冲区溢出攻击原理与防范

缓冲区溢出攻击原理与防范1.程序预留了一块内存区域作为缓冲区,用于执行其中一种特定的操作,如字符串拼接、输入输出处理等;2.当输入的数据长度超过了这个缓冲区的大小时,多余的数据会溢出到相邻的内存区域中;3.攻击者利用输入超出缓冲区的长度来对溢出的数据进行控制,修改程序的执行流程;4.修改后的程序执行流程可以导致程序崩溃、系统崩溃、拒绝服务等问题,也可以用于执行任意的恶意代码。

为了防范缓冲区溢出攻击,可以采取以下几种措施:1.对输入进行有效的长度检查:在程序中对输入数据进行有效的长度检查,确保不会超过预定的缓冲区大小。

这样就可以避免发生缓冲区溢出。

2. 使用安全编程语言和工具:选择使用安全编程语言,如Rust、Go 等,这些语言具有安全性的内存管理机制,能够自动检查和防范缓冲区溢出问题。

此外,使用安全编程工具如静态代码分析工具、Fuzzing工具等也可以帮助发现和修复潜在的缓冲区溢出漏洞。

3.使用内存安全检查工具:使用内存安全检查工具,如利用内存隔离技术的地址空间布局随机化(ASLR)、点火检查器、堆栈保护机制等。

这些工具可以帮助检测和防范缓冲区溢出攻击。

4.最小特权原则:在设计软件时,采用最小特权原则,即仅分配程序所需的最小权限。

这样做可以确保即使发生缓冲区溢出攻击,攻击者也只能访问到最小特权内的信息,减少损失。

5.及时修复漏洞和更新软件:及时修复已知的缓冲区溢出漏洞,更新软件以获取最新的安全补丁是非常重要的。

由于缓冲区溢出攻击是一种常见的攻击方式,软件开发商通常会不断更新修复这方面的漏洞。

综上所述,缓冲区溢出攻击是一种常见的安全漏洞利用技术,可以对各种软件和操作系统进行攻击。

为了防范这种攻击,需要采取有效的措施,如对输入进行有效的长度检查、使用安全编程语言和工具、使用内存安全检查工具、采用最小特权原则以及及时修复漏洞和更新软件等。

这样可以有效地减少缓冲区溢出攻击带来的风险。

缓冲区溢出攻击与防范实验报告

缓冲区溢出攻击与防范实验报告

缓冲区溢出攻击与防范实验报告——计算机网络(2)班——V200748045黄香娥1·缓冲区溢出的概念:缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量溢出的数据覆盖在合法数据上,理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间想匹配,这就为缓冲区溢出埋下隐患.操作系统所使用的缓冲区又被称为"堆栈". 在各个操作进程之间,指令会被临时储存在"堆栈"当中,"堆栈"也会出现缓冲区溢出。

2·缓冲区溢出的危害:在当前网络与分布式系统安全中,被广泛利用的50%以上都是缓冲区溢出,其中最著名的例子是1988年利用fingerd漏洞的蠕虫。

而缓冲区溢出中,最为危险的是堆栈溢出,因为入侵者可以利用堆栈溢出,在函数返回时改变返回程序的地址,让其跳转到任意地址,带来的危害一种是程序崩溃导致拒绝服务,另外一种就是跳转并且执行一段恶意代码,比如得到shell,然后为所欲为。

3·缓冲区溢出原理:由一个小程序来看://test.c#include "stdio.h"#include "stdlib.h"#include "string.h"void overflow(void){char buf[10];strcpy(buf,"0123456789123456789");}//end overflowint main(void){overflow();return 0;}//end main按F11进入"Step into"调试模式,如下:按F11跟踪进入overflow,让程序停在6,现在再看一下几个主要参数:esp=0x0012ff30,eip发生了变化,其它未变。

c语言缓冲区溢出原理

c语言缓冲区溢出原理

c语言缓冲区溢出原理摘要:1.缓冲区溢出概念2.C语言中可能导致缓冲区溢出的原因3.缓冲区溢出的防范方法4.总结正文:正文:缓冲区溢出是计算机科学中的一种常见错误,它在编程中可能导致严重的安全问题。

本文将解释缓冲区溢出的概念,探讨其原因、危害以及如何预防。

一、什么是缓冲区溢出缓冲区溢出是指程序中的缓冲区无法容纳输入的数据,从而覆盖了其他内存区域。

这种情况通常发生在程序没有正确处理输入数据长度的情况下,导致数据超过了缓冲区的容量。

二、缓冲区溢出的原因1.字符串操作函数:在C语言中,一些字符串操作函数(如gets、strcpy 等)没有对输入数据长度进行限制,可能导致缓冲区溢出。

2.动态内存分配:在使用动态内存分配函数(如malloc)分配内存时,如果未正确初始化或超量分配,可能导致缓冲区溢出。

3.函数调用:在调用函数时,如果传入的参数长度超过预期,可能导致缓冲区溢出。

三、缓冲区溢出的危害1.程序崩溃:缓冲区溢出可能导致程序崩溃,因为覆盖的内存区域可能包含程序的重要数据或代码。

2.数据损坏:缓冲区溢出可能导致数据损坏,因为覆盖的内存区域可能包含程序处理数据的正确结果。

3.安全漏洞:缓冲区溢出可能被恶意利用,攻击者可以通过注入恶意数据来覆盖内存中的安全关键数据,如密码、加密密钥等。

四、如何预防缓冲区溢出1.检查输入数据长度:在对输入数据进行处理之前,应检查数据长度,确保不会超过缓冲区容量。

2.使用安全的字符串操作函数:尽量使用带有长度限制的字符串处理函数,如strncpy、strncat等。

3.初始化缓冲区:在使用动态内存分配时,应初始化缓冲区,并确保分配的内存空间足够大。

4.使用边界检查:在编写程序时,对输入数据进行边界检查,确保数据长度符合预期。

缓冲区溢出攻击的原理分析与防范

缓冲区溢出攻击的原理分析与防范

3、缓冲区溢出的防御方法
3.1、写正确的代码的方法 3.2、通过操作系统使得缓冲区不可执行,从而阻止攻击者植入攻击代码 3.3、利用编译器的数组边界检查来实现缓冲区的保护 3.4、在程序指针失效前进行完整性检查
4、总结与展望
4.1全文总结
4.2 展望
5、参考文献
本课题的研究意义
随着信息与网络技术的发展,以及这些技术在军事领域 的不断渗透,计算机网络已成为连接未来信息化战场的枢纽。 对计算机的攻击,能够获得大量宝贵的情报以及达到其它武 器系统所不能及的效果。因此对以计算机为基础的网络攻击 与防护就自然成为军事领域密切关注的问题。近年来,缓冲 区溢出漏洞的广泛性和破坏性受到国内外信息安全研究领域 的极切关注。从1988年CERT(计算机紧急响应小组)成立以来, 统计到的安全威胁事件每年以指数增长。缓冲区溢出攻击作 为网络攻击一种主要形式占所有系统攻击总数的80%以上[1]。 这种缓冲区溢出漏洞可以发生在不同的操作系统以及不同的 应用程序上。 缓冲区溢出攻击是黑客攻击的主要手段,给网络信息安全 带来了越来越大的危害。已有的防御手段研究相对滞后,目 前国内外的研究大多集中在某个具体漏洞的利用与防范上, 缺乏全面的研究。并且现有的缓冲区溢出防御手段也存在诸 多不足之处。论文主要是对缓冲区溢出攻击的原理分析与防 范进行深入研究。 论文首先介绍了缓冲区和堆栈的基本概念,研究并总结了 缓冲区溢出的原理和过程,并介绍了一些常用的攻击方法。 在此基础上,论文研究并总结了目前防御缓冲区溢出攻击的 一些常用方法,主要从主客观两方面来讨论。主观方面,主 要是要提高程序员编写代码的质量,形成良好的编程风格; 客观方面,主要是从系统和软件做一些相关的检查和优化。
缓冲区溢出影响及危害
• 在几乎所有计算机语言中,不管是新的语言还是旧的 语言,使缓冲区溢出的任何尝试通常都会被该语言本身自 动检测并阻止(比如通过引发一个异常或根据需要给缓冲 区添加更多空间),但是有两种语言不是这样:C和C++ 语言。C\C++语言由于其针灵活应用的特性,通常允许让 额外的数据乱写到其余内存的任何位置,而这种情况可能 被利用从而导致意想不到的结果。而且,用C\C++编写正 确的代码来始终如一地处理缓冲区溢出则更为困难;很容 易就会意外地导致缓冲区溢出。更重要的一点就是C\C++ 的应用非常广泛,例如,Red Hat Linux 7.1中86%的代码 行都是用C或C++编写的。因此,大量的代码对这个问题 都是脆弱的,出现缓冲区溢出也就是常见的事情。 缓冲区溢出漏洞很容易被蠕虫病毒利用造成了很大的 危害,如2001年7月19日,CodeRed蠕虫爆发,造成的损 失估计超过20亿美元[2],2001年9月18日,Nimda蠕虫被 发现,造成的损失更大,超过26亿美元,2002年Slapper 蠕虫出现,2003年1月25日Slammer蠕虫爆发,2004年5 月1日,“震荡波”被发现,这几个病毒对网络安全造成 的破坏之大是前所未有的。而以上病毒都利用了缓冲区溢 出漏洞。

缓冲区溢出攻击原理与防范

缓冲区溢出攻击原理与防范

缓冲区溢出攻击的原理与防范陈硕2004-7-12读者基础:熟悉C语言及其内存模型,了解x86汇编语言。

缓冲区溢出(buffer overflow)是安全的头号公敌,据报道,有50%以上的安全漏洞和缓冲区溢出有关。

C/C++语言对数组下标访问越界不做检查,是引起缓冲区溢出问题的根本原因。

本文以Linux on IA32(32-bit Intel Architecture,即常说的x86)为平台,介绍缓冲区溢出的原理与防范措施。

按照被攻击的缓冲区所处的位置,缓冲区溢出(buffer overflow)大致可分为两类:堆溢出1(heap overflow)和栈溢出2(stack overflow)。

栈溢出较为简单,我先以一些实例介绍栈溢出,然后谈一谈堆溢出的一般原理。

栈溢出原理我们知道,栈(stack)是一种基本的数据结构,具有后入先出(LIFO, Last-In-First-Out)的性质。

在x86平台上,调用函数时实际参数(arguments)、返回地址(return address)、局部变量(local variables)都位于栈上,栈是自高向低增长(先入栈的地址较高),栈指针(stack pointer)寄存器ESP始终指向栈顶元素。

以图表1中的简单程序为例,我们先将它编译为可执行文件,然后在gdb中反汇编并跟踪其运行:$ gcc stack.c –o stack -ggdb -mperferred-stack-boundary=2在IA32上,gcc默认按8个字节对齐,为了突出主题,我们令它按4字节对齐,最末一个参数的用处在此。

图表1在每条语句之后列出对应的汇编指令,注意这是AT&T格式汇编,mov %esp, %ebp 是将寄存器ESP的值赋给寄存器EBP(这与常用的Intel汇编格式正好相反)。

// stack.c#01 int add(int a, int b)#02 {// push %ebp// mov %esp,%ebp#03 int sum;// sub $0x4,%esp#04 sum = a + b;// mov 0xc(%ebp),%eax// add 0x8(%ebp),%eax// mov %eax,0xfffffffc(%ebp)#05 return sum;// mov 0xfffffffc(%ebp),%eax1本文把静态存储区溢出也算作一种堆溢出。

缓冲区溢出攻击的原理分析与防范

缓冲区溢出攻击的原理分析与防范

缓冲区溢出攻击的原理分析与防范原理分析:1.缓冲区的分配:当程序运行时,会为其分配一定大小的缓冲区(数组)来存储数据。

攻击者通过输入超过缓冲区大小的数据,覆盖相邻的内存区域。

2. 缓冲区溢出:攻击者构造特定的输入,超过缓冲区的边界,将溢出的数据覆盖到程序的其他内存空间,包括调用栈(stack)等。

3.返回地址覆盖:返回地址是指程序执行的下一条指令的地址,攻击者通过溢出缓冲区,将恶意代码的地址覆盖到返回地址上,使程序执行恶意代码。

4.执行恶意代码:当程序执行到返回地址时,由于返回地址被替换为恶意代码的地址,程序控制权转移到了恶意代码上,攻击者可以控制程序执行一系列恶意操作。

防范措施:1. 输入验证:在程序中对用户输入进行验证和过滤,确保输入的大小不会超出缓冲区的边界。

可以使用编程语言中的字符串处理函数,如strncpy(、snprintf(等,确保只将有效数据拷贝到缓冲区。

2. 使用编程语言和框架提供的安全API:使用编程语言提供的安全API,如Java中的StringBuilder类,C#中的StringBuilder类等,这些API在处理字符串时会进行边界检查,避免缓冲区溢出。

3. 栈保护技术:栈保护技术包括Stack Smashing Protector (SSP)和Control Flow Integrity (CFI)等。

SSP通过在栈上插入一个特殊的栈保护变量,监控缓冲区的溢出情况。

CFI通过在程序中插入额外的代码和元数据,来防止控制流的恶意改变。

4. 内存随机化:通过内存随机化技术,如ASLR(Address Space Layout Randomization),将程序的内存布局随机化,使攻击者难以预测恶意代码的位置。

5.使用静态和动态代码分析工具:使用静态和动态代码分析工具来检测和修复程序中的缓冲区溢出漏洞。

静态代码分析工具可以在编译时检测潜在的缓冲区溢出漏洞,而动态代码分析工具可以模拟攻击,并检测运行时的缓冲区溢出情况。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

摘要:正文:大纲:1.引言;随着网络安全技术的飞速发展,缓冲区溢出漏洞已经成为当前最具安全威胁的漏洞之一,缓冲区溢出攻击也成为一种非常有效而常见的攻击方法。

如Internet上的第1例蠕虫(Morris)攻击,就是利用了fingerd的缓冲区溢出漏洞。

SANS评选出的2005年威胁最大的20个漏洞中,有8个跟缓冲区溢出有关。

根据CNCERT最近几周的计算机安全漏洞的统计数据,与缓冲区溢出有关的安全事件占了很大的比例。

这些都充分说明了研究缓冲区溢出的重要性。

本文主要介绍了windows下的缓冲区溢出的相关知识。

2.漏洞原因和原理;2.1 产生原因;当向一个已分配了确定存储空间的缓冲区内复制多于该缓冲区处理能力的数据时,就会发生缓冲区溢出,溢出包括堆溢出和堆栈溢出。

它与程序在内存中的分布有关,而它产生的直接原因是由于C/C++程序中的一些函数调用时,没有进行边界检查,如C函数库中的strcpy(),strcat(),sprintf(),gets()等都是不安全的。

由上面的分析可知要产生缓冲区溢出,需要有几个条件: 1) 程序编译时在堆栈上分配了固定大小的缓冲区,并且在对缓冲区进行访问时没有提供边界检查。

这条在C/C ++语言中就满足,而对于有边界检查的语言,如Pascal 等,就没有这样的溢出问题。

2) 程序调用了没有进行边界检查的函数来访问(写操作) 缓冲区,这些函数没有对访问的缓冲区的大小进行判断。

由于在C语言中,字符串以0字节来标识结尾,其中没有字符串的长度信息,所以几个没有判断字符串长度的字符串拷贝函数就是容易出现问题的函数。

这些函数有: strcat()、strcpy()、sprintf()等。

3) 即使程序使用了上面所说的问题函数也不一定会出现溢出漏洞,漏洞发生的最后一个条件是程序员由于粗心,未检查用户输入数据的长度就将其直接复制到缓冲区中去。

虽然这看起来是一件小事,很容易杜绝。

可惜的是正因为有大量粗心的程序员的存在,使得溢出漏洞变得非常的普遍。

2.2 原理;图1 堆栈缓冲区示意图程序的堆栈是先进后出的一种数据结构,堆栈的生长方向适合内存相反的(如图1)。

当调用一个函数时,首先是函数的参数逆序进栈,然后将eip里面的内容进栈作为函数的返回地址(ret),即函数调用结束后程序跳转的地址,接着保存现在程序的栈基指针(ebp),并将当前栈顶指针(esp)拷入ebp作为新的基地址.最后将esp减去一定数值用来为本地变量留出一定空间。

缓存区往往就分配在这段空间中。

由于堆栈是由内存高地址向内存低地址方向增长,而数组的变量是从内存低地址向高地址方向增长,这时如果没有对数组的越界进行检查和限制,通过向程序的数组缓冲区写入超出其长度的内容,覆盖堆栈原来的返回地址(ret),就会造成缓冲区溢出,从而破坏程序的堆栈。

如果构造特殊的注入向量覆盖ret值使程序转而执行恶意代码(shellcode),就达到攻击的目的。

3.基于缓冲区漏洞的攻击过程;由上所述可知,堆栈缓冲区溢出漏洞的攻击利用的3个步骤是:1)溢出点ret的定位;定位ret 的流程是用一定格式的字符串覆盖存在溢出漏洞的缓冲区,使程序溢出,然后根据溢出结果计算ret 的位置。

最常用的方法是利用报错对话框精确计算出溢出返回点的方法,如图2中的报错对话框所示,可以看到是“0x79797979”覆盖到了溢出点。

依次类推,我们可以不断给一个数组反复赋值,利用整除和求余等数学方法来精确计算溢出点的位置。

图2 溢出报错对话框2)构造shellcode;确定下来溢出点位置后,就需要有可以执行的shellcode来达到入侵的目的。

shellcode的编写主要有两种lodsd方法,一是用C等高级语言编写经反汇编后提取二进制码。

二是直接使用汇编语言编写并提取二进制码。

使用c语言编写生成的代码较长,但编写调试简单,且可以根据不同的需要灵活更改代码。

而利用汇编语言生成的代码更为简练,但调试复杂,一旦编写成功后不易修改。

3)用特定地址覆盖ret并且使其跳转到shellcode,并执行。

是将返回点覆盖成jmp esp或call ebx的地址。

为了通用性使用kernel32.dll中的指令地址.因为同一系统中该模块装载地址变化可能小。

覆盖方法主要有两种:①NNNNNNNNNSSSSSSSSSSSRRRRRRRRRRRRRR型。

适合于大缓冲区,“N”代表空指令(NOP),也就是0x90,在实际运行中,程序将什么也不做,而是一直延着这些NOPS运行下去,直到遇到不是NOPS的指令再执行之;“S”代表ShellCode;“R”代表覆盖的返回地址,思路是把返回地址R覆盖为nops的大概位置,这样就会跳到Nop中,然后继续执行,直到我们的ShellCode中。

但这种方法由于定位不准确,所以使用起来也不准确。

②RRRRRRRRRRNNNNNNNNNNNSSSSSSSSSS型。

是用大量的“R”填满整个缓冲区,然后大量的Nop,最后是ShellCode。

这里,“R”往后跳到Nop中,再顺着往下执行就会到ShellCode中。

但在Windows下,“R”中必定会含有0,这样,整个构造就会被截断,所以这种方法只能用于Unix中。

图3 Windows缓冲区分布Windows的系统核心dll包括kernel32.dll、user32.dll、gdi32.dll。

这些dll一直位于内存中,而且对应于固定的版本,Windows加载的位置是固定的。

用系统核心dll中的jmp esp 地址来覆盖返回地址,而把ShellCode紧跟在后面,这样就可跳转到我们的ShellCode中。

其利用格式是NNNNNNRSSSSSS,N=Nop,S=ShellCode,R=jmp esp的地址。

如图3所示。

常用的JMP ESP的地址:0x7ffa4512(winXP/win2003通用);又是我们还可以利用JMP EBX的地址:0x7ffa1571(winXP/win2003通用);4.检测方法及防范措施;根据缓冲区溢出攻击的步骤,可将常用的缓冲区溢出攻击检测技术分为以下3 种类型:基于输入字符串的检测方法,基于保护堆栈中的返回地址的检测方法和基于监视系统调用的检测方法。

4.1 基于输入字符串的检测方法对输入的字符串进行检测,确定其为溢出攻击字符串时采取阻拦措施,使攻击者无法注入攻击代码。

一般有以下3 种方法构建溢出攻击字符串。

分别如下图4-1,图4-2,图4-3所示:图4-1 缓冲区大于ShellCode 长度图4-2缓冲区小于ShellCode 长度图4-3将ShellCode 放在环境变量里第1 种溢出攻击字符串适用于缓冲区大于ShellCode 长度的情况;第2 种溢出攻击字符串一般用于缓冲区小于ShellCode 长度的情况;第3 种方法是将ShellCode 放在环境变量里,是目前较为常用的方法。

在第1 种和第2 种类型的溢出攻击字符串中ShellCode前都加了若干的NOP 指令,因为这2 种情况下ShellCode 的地址无法确定,但只要返回地址指向ShellCode 前的任一条NOP 指令,ShellCode 就可以执行,大大增加了ShellCode 执行的可能性。

这些NOP 指令称为sledge。

其他单字节指令如AAA 等也可构成sledge。

因此缓冲区溢出攻击检测系统可以通过检查输入的字符串中是否含有大量NOP 等可构成sledge的指令来判断此字符串是否是溢出攻击字符串。

不过这种方法并不适用于检测第3 种类型的攻击。

但这3 种类型的攻击字符串中都含有ShellCode。

因此,确定出ShellCode 的基本特征,如不含有“0x00”,含有某些特殊的系统调用等,然后利用人工智能、模式匹配、规则匹配等方法检查输入字符串中是否包含ShellCode 也可检测出是否有缓冲区溢出攻击发生。

这些检测都可以在入侵检测等外围防御系统中实现,优点是实现较为简单,不会增加被保护系统的开销;缺点是漏报率较高,无法检测出无明显特征的溢出攻击字符串。

4.2基于保护堆栈中返回地址的检测方法缓冲区溢出攻击最关键的步骤是要通过修改函数返回地址来改变程序的流程,因此,在函数调用返回前,通过检查返回地址是否被修改可以判断是否有缓冲区溢出攻击发生。

该检测的实现可以通过在源码中插入一些约束和判断的模块,然后在编译后的程序运行期间对有关变量和堆栈区域进行监控,检测是否有攻击发生。

StackGuard 和StackShield 就是这一类型的工具,它们都是gcc 编译器的扩展工具,用于监控调用的函数返回地址是否正常。

StackGuard 主要是在内存中的返回地址及缓冲区之间插入一个“Canary”字,如图5 所示。

在函数调用返回前通过检查“Canary”字来判断返回地址是否已经被修改,如果这个Canary 的值被改变了,说明可能有人正进行缓冲区溢出攻击,程序会立刻响应,发送一则入侵警告消息,然后停止工作。

为防止攻击者构造“Canary”字,StackGuard 选用“终止符”和“随机数”作为“Canary”字的值。

但由于“Canary”字所在的位置是固定的,因此也可能被绕过。

StackShield 对此作了改进,创建了一个新的堆栈用于备份被保护函数的返回地址。

它在被保护函数开始处增加一段代码,用来将函数返回地址拷贝到一张特殊的表中;同样在被保护函数的结尾处也增加一段代码,用来将函数返回地址从表中拷贝回堆栈。

从而保证函数正确返回。

除这 2 种工具外,还有其他一些类似的编译器扩展方法和工具,如PointGuard、Snarskii 等。

这些工具提高了被保护系统的安全性,不过增加了系统开销,降低了系统性能。

4.3 基于监视系统调用的检测方法如果攻击者成功注入攻击代码,并改变了程序的执行流程使指令的执行指针指向了ShellCode 的入口地址。

按照一次缓冲区攻击的3 个步骤,还须执行ShellCode 来完成攻击目的。

因此,通过检测是否有ShellCode 运行可以检测是否发生缓冲区溢出攻击。

攻击者既希望ShellCode 利用获得的权限启动一个交互式的shell 进程来完成尽量多的事情,又希望ShellCode 尽量短小从而更加隐蔽,所以绝大多数ShellCode 都会调用系统函数。

由于监视所有系统调用会耗费大量系统资源,因此只对ShellCode 常用的系统调用进行监视,根据某些特征判断受监视的系统调用是否为非法调用就可确定被保护系统是否遭到缓冲区溢出攻击。

例如,如果发现系统调用的返回地址为堆栈,则可认为其为非法调用,因为很少有程序在堆栈上运行代码。

4.4缓冲区漏洞的防范措施上面三种方法是针对如何检测已经发生的缓冲区漏洞,方法虽然多,但是相对比较麻烦,所以我们最好能从根本上防范它,防止缓冲区漏洞的发生。

相关文档
最新文档