缓冲区溢出漏洞是一种常见的安全漏洞,广泛存在于各种应用软件和操作系统之中。它产生的原理是,进程在存储临时数据时没有对数据的长度进行合理性检查,导致内存中的某些重要数据被覆盖,从而引发了安全问题。进程中某些缓冲区漏洞被恶意攻击者利用后,会产生严重的系统安全问题。“缓冲区”是指进程中用来保存临时数据的一段内存,可以分为栈缓冲区和堆缓冲区两种。对缓冲区溢出漏洞进行攻击,会导致进程死亡、系统宕机以及主机重启等后果。更为严重的是,如果攻击者的攻击效果完美,系统会在受害者没有任何察觉的情况下就被对方控制了。在所有的缓冲区溢出漏洞中,栈溢出漏洞是最简单也是最危险的一种。攻击者对栈溢出漏洞进行攻击时,可以植入攻击载荷,然后改变函数返回地址 EIP 使其指向攻击载荷。
很多情况下缓冲区溢出漏洞和堆溢出漏洞、栈溢出漏洞被混为一谈,这是及其不准确的说法。产生这种错误说法的原因是平时所遇到的大部分缓冲区溢出漏洞是由栈溢出和堆溢出引起的。缓冲区溢出是一个很大的概念,所有由超长数据引发的内存溢出都属于缓冲区溢出,但是堆溢出和栈溢出只是缓冲区溢出中的一个子集。在程序的编写过程中,程序员经常会直接开辟一段内存空间去存储数据。这些在堆中或栈中直接开辟的内存空间大小是有限的,当进程将未经检查的数据直接存入这段内存中时,就会产生堆溢出或栈溢出。堆溢出和栈溢出最为直接的危害是,存入内存的超长数据会将进程中的重要数据覆盖,从而产生不可预知的后果。
在栈溢出中有一个“返回地址”的概念,此概念来源于 CPU 处理指令。如果某个进程准备调用函数,操作系统首先会将此函数的下一条指令的指针存储到栈空间 EIP;然后,系统开始执行函数;函数执行完毕,系统会取出 EIP 中保存的指针,并跳转到这条指令上去执行。进程将函数的“返回地址”EIP 保存在栈内存,而函数中的临时存储空间一般也是在栈内存中进行开辟的,这就给了恶意攻击者覆盖这个 EIP 指针的机会。