Author : Cyan_RA9
Source : 【卡码笔记】网站
Question : 解释一下缓冲区溢出攻击,以及如何防范?
【简要回答】
- 缓冲区溢出攻击的定义:
- “缓冲区溢出攻击”是一种利用程序内存安全漏洞的攻击手段,指攻击者通过向程序的内存缓冲区写入超出其容量的数据,覆盖相邻内存区域,从而篡改程序执行流程或注入恶意代码。
- 如何防范缓冲区溢出攻击
- 编程层:
① 安全函数:使用snprintf()、strncpy()等限制长度的函数。
② 安全语言:优先选择 Rust、Java 等自动管理内存的语言。 - 操作系统层:
① 数据执行保护(DEP):标记内存页为不可执行(NX 位),阻止 Shellcode 运行。
② 地址空间随机化(ASLR):随机化代码段、堆栈基址,增加预测跳转地址难度。
- 编程层:
【详细回答】
- 定义:
- 缓冲区溢出攻击是一种利用程序内存安全漏洞的攻击手段,攻击者会利用程序没有正确检查输入数据边界的漏洞,向内存缓冲区(如栈、堆、全局数据区)写入超量数据,以此来覆盖相邻内存区域,从而修改函数的返回地址,劫持程序执行流程;或者覆盖函数指针或对象元数据,触发恶意代码执行;或者篡改变量值,破坏程序逻辑。
- 分类:
-
栈溢出(Stack Overflow):
覆盖栈上的返回地址,跳转到攻击者控制的代码(Shellcode)。eg :void vulnerable(char * input) { char buffer[64]; strcpy(buffer, input); // No Boundary-Check. } -
堆溢出(Heap Overflow):
篡改动态分配内存(malloc/free)的管理结构(如 chunk metadata),触发任意地址写入。 -
全局数据区溢出:
覆盖全局变量或静态存储区的数据,影响程序的全局状态,可能使数据不可用,并最终导致程序崩溃。
-
- 后果:
- 任意代码执行:
攻击者可以精心构造溢出数据,精确覆盖函数返回地址或函数指针,使其指向攻击者注入的恶意代码(shellcode)。这样一来攻击者可以获取系统控制权(如开启远程 shell),或者窃取敏感数据(如数据库、密码文件)。 - 经典案例:
Morris蠕虫(1988年)、CodeRed(2001年)均利用缓冲区溢出。
- 任意代码执行:
- 防范措施:
- 编程层:
① 安全函数:使用snprintf()、strncpy()等限制长度的函数。
② 安全语言:优先选择 Rust、Java 等自动管理内存的语言。 - 操作系统层:
① 数据执行保护(DEP):标记内存页为不可执行(NX 位),阻止 Shellcode 运行。
② 地址空间随机化(ASLR):随机化代码段、堆栈基址,增加预测跳转地址难度。
- 编程层:
【知识拓展】
- Buffer Overflow Attack,一张示意图如下:
- 缓冲区溢出攻击真实案例 —— 莫里斯蠕虫 (Morris Worm, 1988年):
- 背景:这是互联网历史上第一个通过网络传播的蠕虫程序,它利用了早期 Unix 系统中 fingerd(用户信息查询工具) 服务的缓冲区溢出漏洞。
- 原理: fingerd 服务使用了 C 语言中的标准库函数 gets()。gets() 函数在读取输入时不检查边界。攻击者向该服务发送了一段精心设计的超长字符串。这段字符串溢出了为用户输入分配的栈缓冲区,直接覆盖了函数调用的返回地址(Return Address)。攻击者将返回地址指向了他们植入栈中的一段恶意代码(Shellcode)。然后,当函数执行完毕准备返回时,CPU 跳到了恶意代码处执行,从而获得了系统的控制权。
- 威力:Morris Worm 在几个小时内感染了当时全球约 10% 的互联网连接计算机(约 6000 台),导致网络瘫痪。这直接促成了第一个计算机应急响应小组(CERT)的成立。
- DoS Attack (Denial of Service) :
A Denial-of-Service (DoS) attack aims to disrupt legitimate access to a service by exhausting its resources (e.g., CPU, memory, bandwidth) or exploiting vulnerabilities to crash the system. For example, a buffer overflow could overwrite critical program data, causing the service to terminate abruptly. Unlike DDoS (Distributed DoS), a DoS attack typically originates from a single source. Defenses include input validation, rate limiting, and redundancy mechanisms like load balancing.