溢出(溢出overflow樱花制作公司第七集)

2023-03-04 14:53:34 发布:网友投稿 作者:网友投稿
热度:81

溢出程序设计者设计时的不足所带来的错误

溢出是黑客利用操作系统的漏洞,专门开发了一种程序,加相应的参数运行后,就可以得到你电脑具有管理员资格的控制权,你在你自己电脑上能够运行的东西他可以全部做到,等于你的电脑就是他的了。 溢出可分为缓冲区溢出、内存溢出、数据溢出等多类,使缓冲区溢出的任何尝试通常都会被该语言本身自动检测并阻止。

中文名

溢出

buffers

长跳转缓冲区

激活纪录

Activation Records

分类

缓冲区溢出

基本介绍

溢出是在你自己电脑上能够运行的东西他可以全部做到,等于你的电脑就是他的了。 在黑客频频攻击、在系统漏洞层出不穷的今天,作为网络管理员、系统管理员的我们虽然在服务器的安全上都下了不少功夫:诸如,及时的打上系统安全补丁、进行一些常规的安全配置,但是仍然不太可能每台服务器都会在第一时间内给系统打上全新补丁。 因此我们必需要在还未被入侵之前,通过一些系列安全设置,来将入侵者们挡在“安全门”之外。

溢出分类

1.1在程序的地址空间里安排适当的代码

1.1.1殖入法

攻击者用被攻击程序的缓冲区来存放攻击代码。 攻击者向被攻击的程序输入一个字符串,程序会把这个字符串放到缓冲区里。 这个字符串包含的数据是可以在这个被攻击的硬件平台上运行的指令序列。

1.1.2利用已经存在的代码

有时候,攻击者想要的代码已经在被攻击的程序中了,攻击者所要做的只是对代码传递一些参数,然后使程序跳转到指定目标。 比如,在C语言中,攻击代码要求执行“exec("/bin/sh")”,而在libc库中的代码执行“exec(arg)”,其中arg是指向一个字符串的指针参数,那么攻击者只要把传入的参数指针指向"/bin/sh",就可以调转到libc库中的相应的指令序列。

1.2控制程序转移到攻击代码

这种方法旨在改变程序的执行流程,使之跳转到攻击代码。 最基本方法的就是溢出一个没有边界检查或者其他弱点的缓冲区,这样就扰乱了程序的正常的执行顺序。 通过溢出一个缓冲区,攻击者可以用近乎暴力的方法改写相邻的程序空间而直接跳过了系统的检查。

1.2.1激活纪录(ActivationRecords)

每当一个函数调用发生时,调用者会在堆栈中留下一个激活纪录,它包含了函数结束时返回的地址。 攻击者通过溢出这些自动变量,使这个返回地址指向攻击代码。 通过改变程序的返回地址,当函数调用结束时,程序就跳转到攻击者设定的地址,而不是原先的地址。 这类的缓冲区溢出被称为“stacksmashingattack”,是目前常用的缓冲区溢出攻击方式。

1.2.2函数指针(FunctionPointers)

C语言中,“void(*foo)()”声明了一个返回值为void函数指针的变量foo。 函数指针可以用来定位任何地址空间,所以攻击者只需在任何空间内的函数指针附近找到一个能够溢出的缓冲区,然后溢出这个缓冲区来改变函数指针。 在某一时刻,当程序通过函数指针调用函数时,程序的流程就按攻击者的意图实现了!它的一个攻击范例就是在Linux系统下的superprobe程序。

1.2.3长跳转缓冲区(Longjmpbuffers)

在C语言中包含了一个简单的检验/恢复系统,称为setjmp/longjmp。 意思是在检验点设定“setjmp(buffer)”,用“longjmp(buffer)”来恢复检验点。 然而,如果攻击者能够进入缓冲区的空间,那么“longjmp(buffer)”实际上是跳转到攻击者的代码。 象函数指针一样,longjmp缓冲区能够指向任何地方,所以攻击者所要做的就是找到一个可供溢出的缓冲区。 一个典型的例子就是Perl5.003,攻击者首先进入用来恢复缓冲区溢出的的longjmp缓冲区,然后诱导进入恢复模式,这样就使Perl的解释器跳转到攻击代码上了!

最简单和常见的缓冲区溢出攻击类型就是在一个字符串里综合了代码殖入和激活纪录。 攻击者定位一个可供溢出的自动变量,然后向程序传递一个很大的字符串,在引发缓冲区溢出改变激活纪录的同时殖入了代码。 这个是由Levy指出的攻击的模板。 因为C语言在习惯上只为用户和参数开辟很小的缓冲区,因此这种漏洞攻击的实例不在少数。

代码殖入和缓冲区溢出不一定要在一次动作内完成。 攻击者可以在一个缓冲区内放置代码,这是不能溢出缓冲区。 然后,攻击者通过溢出另外一个缓冲区来转移程序的指针。 这种方法一般用来解决可供溢出的缓冲区不够大的情况。

如果攻击者试图使用已经常驻的代码而不是从外部殖入代码,他们通常有必须把代码作为参数化。 举例来说,在libc中的部分代码段会执行“exec(something)”,其中something就是参数。 攻击者然后使用缓冲区溢出改变程序的参数,利用另一个缓冲区溢出使程序指针指向libc中的特定的代码段。

为什么缓冲区溢出如此常见

在几乎所有计算机语言中,不管是新的语言还是旧的语言,使缓冲区溢出的任何尝试通常都会被该语言本身自动检测并阻止(比如通过引发一个异常或根据需要给缓冲区添加更多空间)。 但是有两种语言不是这样:C和C++语言。 C和C++语言通常只是让额外的数据乱写到其余内存的任何位置,而这种情况可能被利用从而导致恐怖的结果。 更糟糕的是,用C和C++编写正确的代码来始终如一地处理缓冲区溢出则更为困难;很容易就会意外地导致缓冲区溢出。 除了C和C++使用得非常广泛外,上述这些可能都是不相关的事实;例如,RedHatLinux7.1中86%的代码行都是用C或C++编写的。 因此,大量的代码对这个问题都是脆弱的,因为实现语言无法保护代码避免这个问题。

在C和C++语言本身中,这个问题是不容易解决的。 该问题基于C语言的根本设计决定(特别是C语言中指针和数组的处理方式)。 由于C++是最兼容的C语言超集,它也具有相同的问题。 存在一些能防止这个问题的C/C++兼容版本,但是它们存在极其严重的性能问题。 而且一旦改变C语言来防止这个问题,它就不再是C语言了。 许多语言(比如Java和C#)在语法上类似C,但它们实际上是不同的语言,将现有C或C++程序改为使用那些语言是一项艰巨的任务。

然而,其他语言的用户也不应该沾沾自喜。 有些语言存在允许缓冲区溢出发生的“转义”子句。 Ada一般会检测和防止缓冲区溢出(即针对这样的尝试引发一个异常),但是不同的程序可能会禁用这个特性。 C#一般会检测和防止缓冲区溢出,但是它允许程序员将某些例程定义为“不安全的”,而这样的代码可能会导致缓冲区溢出。 因此如果您使用那些转义机制,就需要使用C/C++程序所必须使用的相同种类的保护机制。 许多语言都是用C语言来实现的(至少部分是用C语言来实现的),并且用任何语言编写的所有程序本质上都依赖用C或C++编写的库。 因此,所有程序都会继承那些问题,所以了解这些问题是很重要的。

防止缓冲区溢出的新技术

当然,要让程序员不犯常见错误是很难的,而让程序(以及程序员)改为使用另一种语言通常更为困难。 那么为何不让底层系统自动保护程序避免这些问题呢?最起码,避免stack-smashing攻击是一件好事,因为stack-smashing攻击是特别容易做到的。

一般来说,更改底层系统以避免常见的安全问题是一个极好的想法,我们在本文后面也会遇到这个主题。 事实证明存在许多可用的防御措施,而一些最受欢迎的措施可分组为以下类别:

基于探测方法(canary)的防御。 这包括StackGuard(由Immunix所使用)、ProPolice(由OpenBSD所使用)和Microsoft的/GS选项。

非执行的堆栈防御。 这包括SolarDesigner的non-exec补丁(由OpenWall所使用)和execshield(由RedHat/Fedora所使用)。

其他方法。 这包括libsafe(由Mandrake所使用)和堆栈分割方法。

遗憾的是,迄今所见的所有方法都具有弱点,因此它们不是万能药,但是它们会提供一些帮助。

参考资料

1.溢出·王朝网络

下一篇:桃园经验(桃园经验知乎)
上一篇:奢侈(奢侈品女包十大名牌排行榜)