缓冲区溢出攻击:定义、类型及如何避免
什么是缓冲区溢出?
当向缓冲区写入的数据量超过其容量时,就会发生缓冲区溢出。多余的数据会被写入到相邻的内存中,覆盖该位置的内容,并导致程序结果不可预测。缓冲区溢出发生在数据写入时没有进行充分的验证(没有边界检查)的情况下。它被视为软件中的一个缺陷或漏洞。
通过在数据集的初始部分引入专门设计用来导致缓冲区溢出的代码,攻击者可以利用缓冲区溢出问题,然后将剩余的数据写入溢出缓冲区相邻的内存地址。
溢出的数据可能包含可执行代码,允许攻击者运行更大、更复杂的程序或获得系统访问权限。
缓冲区溢出是攻击者可能利用的最致命的漏洞之一,部分原因在于它们难以检测和修复,尤其是在包含数百万行代码的软件中。即使是这些错误的修复也复杂且容易出错。因此,消除此类问题几乎是不可能的。
即使许多程序员意识到程序中缓冲区溢出的风险,但在新旧软件中仍然存在许多与缓冲区溢出相关的危害,无论已经实施了多少补丁。
缓冲区到底是什么?
缓冲区,也称为数据缓冲区,是用于临时存储数据的物理内存存储区域。同时,它正在从一个位置传输到另一个位置。这些缓冲区通常存储在 RAM 中。计算机经常使用缓冲区来提高性能;大多数当前的硬盘驱动器都使用缓冲区来更快地检索数据,并且许多在线服务也这样做。例如,缓冲区被广泛用于防止互联网视频流中断。当视频流式传输时,视频播放器首先下载并存储大约 20% 的视频到缓冲区中,然后从该缓冲区进行流式传输。连接速度的微小下降或短暂的服务中断不会影响视频流的性能。
缓冲区用于存储特定数量的信息。除非使用缓冲区的程序具有内置指令在发送过多数据时丢弃数据,否则缓冲区相邻内存中的数据将被覆盖。
攻击者可以利用缓冲区溢出来破坏软件。缓冲区溢出攻击尽管已被充分理解,但仍然是一个严重的安全问题,困扰着网络安全团队。由于 SSL 软件中的缓冲区溢出漏洞,2014 年一个称为“心脏出血”的威胁使数亿人面临攻击。
缓冲区溢出攻击的类型
缓冲区溢出攻击有多种形式。用于利用缓冲区溢出漏洞的操作系统 (OS) 和编程语言有所不同。目标始终是通过操纵计算机的内存来颠覆或控制程序执行。
缓冲区溢出根据缓冲区在进程内存中的位置进行分类。基于堆栈或基于堆的溢出最为常见。两者都存储在设备的随机存取内存中。
以下是缓冲区溢出攻击的示例。
基于堆栈的缓冲区溢出
它通常被称为**堆栈缓冲区溢出**,一种缓冲区溢出攻击。堆栈以后进先出结构存储数据。它是一个连续的内存空间,用于排列与函数调用相关的数据,例如函数参数、函数局部变量和管理信息,如帧和指令指针。
堆栈通常为空,直到目标软件请求用户输入,例如登录名或密码。然后,程序在将用户的输入放在其顶部之前,将返回内存地址写入堆栈。当处理堆栈时,用户的输入被传输到程序设置的返回地址。
另一方面,堆栈具有固定的大小。代码开发人员必须为堆栈预留一定数量的空间。如果用户的输入长度超过堆栈中指定的空间量,并且软件未验证输入是否适合,则堆栈将溢出。这本身并不是一个重大问题,但当与恶意输入结合时,它就成为一个主要的安全性漏洞。
基于堆的缓冲区溢出攻击
堆是用于存储和管理动态数据的内存结构。当请求的内存量过大以至于无法放入堆栈或内存旨在跨函数调用使用时,程序员通常使用堆来分配在编译时大小未知的内存。基于堆的攻击会淹没程序或进程的内存区域。基于堆的漏洞,例如今年早些时候发现的 Google Chrome 零日漏洞,比堆栈攻击更难以利用。
整数溢出攻击
在整数长度限制内,当某些限制被超过时,结果可能是错误或不准确的结果。当整数用于算术运算,并且输出值大于整数的最大大小时,就会发生整数溢出攻击。例如,需要 8 位 RAM 来保存数字 192。如果该过程将 64 加到此数字,则结果 256 将无法放入分配的内存中,因为它需要 9 位。
格式字符串攻击
通过利用字符串格式化库操作(如 printf 和 sprintf)来访问和修改其他内存位置,攻击者可以影响应用程序的运行方式。
Unicode 溢出攻击
这些漏洞利用了以下事实:以 Unicode 格式存储字符串比以 ASCII 字符存储字符串需要更多的内存。它们可以用来攻击仅接受 ASCII 字符作为输入的程序。
缓冲区溢出 - 如何避免它们
可以通过在开发代码中包含安全功能、采用具有内置保护的编程语言以及彻底测试代码以发现和纠正错误来避免缓冲区溢出。
避免使用未进行边界检查的标准库函数(如 gets、scanf 和 strcpy)是防止缓冲区溢出最常用的方法之一。另一种常见的防止缓冲区溢出的方法是在运行时实现边界检查。这确保自动将推送到缓冲区的数据保持在正确的边界内。
现代操作系统现在包括运行时保护,这为防止缓冲区溢出增加了额外的防御层。这包括标准安全措施,例如 -
**地址空间布局随机化 (ASLR)** - 缓冲区溢出攻击通常需要知道可执行代码位于何处。这就是地址空间布局随机化 (ASLR) 的作用。ASLR 将数据区域随机移动到随机地址空间,使溢出攻击几乎不可能。
**数据执行保护** - 此方法将内存部分标记为可执行或不可执行,从而防止攻击在不可执行区域运行代码。
**结构化异常处理 (SEHOP) 的覆盖保护** - 攻击者可能会尝试覆盖结构化异常处理 (SEH),这是一种用于管理硬件和软件异常的内置机制。他们通过使用基于堆栈的溢出攻击覆盖存储在程序堆栈上的异常注册记录来做到这一点。SEHOP 防止恶意程序攻击 SEH 并利用其覆盖利用机制。
围绕开发代码和操作系统的安全措施不足以保护组织的系统。当检测到缓冲区溢出漏洞时,务必尽快修复软件并将其提供给所有用户。
数据结构
网络
RDBMS
操作系统
Java
iOS
HTML
CSS
Android
Python
C 编程
C++
C#
MongoDB
MySQL
Javascript
PHP