【缺陷周话】第9期:缓冲区下溢
字数 1924 2025-08-18 11:37:45
缓冲区下溢漏洞分析与防护指南
1. 缓冲区下溢概述
缓冲区下溢是C/C++程序中一种严重的安全漏洞类型,属于缓冲区溢出的一种特殊情况。当填充数据溢出时,溢出部分覆盖的是下级缓冲区(内存中更低地址的区域),这与缓冲区上溢(覆盖上级缓冲区)形成对比。
基本特征:
- 发生在内存操作过程中,特别是字符串操作
- 由于目的缓冲区小于源缓冲区导致
- 可能导致程序崩溃、执行任意代码或权限提升
2. 缓冲区下溢的危害
缓冲区下溢可能造成以下严重后果:
- 程序崩溃:破坏关键数据结构导致程序异常终止
- 执行恶意代码:精心构造的溢出数据可能被执行为代码
- 权限提升:如CVE-2018-1000001中通过SUID binary获取root权限
- 拒绝服务:如CVE-2018-5388中导致资源耗尽
根据CVE统计,2018年1-10月就有494个相关漏洞记录。
3. 典型漏洞案例分析
3.1 CVE-2018-1000001 (Libc Realpath漏洞)
- 原因:GNU C库未正确处理getcwd()返回的相对路径
- 影响:通过SUID binary可获得root权限
- 严重性:高危
3.2 CVE-2018-1000637 (zutils zcat漏洞)
- 原因:处理特制压缩文件时的缓冲区溢出
- 影响:拒绝服务或任意代码执行
- 版本:影响1.8-pre2之前版本
3.3 CVE-2018-5388 (strongSwan漏洞)
- 原因:缓冲区下溢
- 影响:资源耗尽导致拒绝服务
- 版本:影响5.6.3之前版本
4. 代码示例分析
4.1 缺陷代码示例
char * data;
char dataBadBuffer[10];
char dataGoodBuffer[10+1];
strcpy(dataBadBuffer, "AAAAAAAAAA"); // 10个A
data = dataBadBuffer; // 指向只有10字节的缓冲区
strcpy(data, source); // source长度超过10导致下溢
问题点:
- 使用固定大小的缓冲区(dataBadBuffer)存储可能超长的数据
- 使用不安全的strcpy()函数而没有长度检查
- 目的缓冲区(dataBadBuffer)小于源缓冲区(source)
4.2 修复代码示例
char * data;
char dataBadBuffer[10];
char dataGoodBuffer[10+1];
strcpy(dataGoodBuffer, "AAAAAAAAAA"); // 10个A
data = dataGoodBuffer; // 指向11字节的缓冲区
strcpy(data, source); // 现在缓冲区足够大
修复方法:
- 确保目的缓冲区足够大(dataGoodBuffer[10+1])
- 仍然建议使用更安全的函数替代strcpy()
5. 检测与防护措施
5.1 检测方法
- 静态代码分析工具(如360代码卫士)
- 动态运行时检测
- 代码审查重点关注:
- 不安全的字符串操作函数(strcpy, strcat等)
- 固定大小的缓冲区
- 缺少边界检查的循环
5.2 防护措施
5.2.1 编码实践
-
避免使用不安全函数:
- 用strncpy()替代strcpy()
- 用snprintf()替代sprintf()
- 用fgets()替代gets()
-
边界检查:
if(strlen(source) < sizeof(dest)) { strncpy(dest, source, sizeof(dest)-1); dest[sizeof(dest)-1] = '\0'; } -
使用安全字符串库:
- 如Safe C Library、Microsoft的STRSAFE库
-
编译器选项:
- 开启栈保护(-fstack-protector)
- 启用堆栈不可执行(DEP/NX)
- 地址空间布局随机化(ASLR)
5.2.2 防御性编程
- 始终假设输入可能是恶意的
- 对来自外部的所有数据进行严格验证
- 使用自动化工具进行定期代码审计
6. 相关CWE分类
- CWE-121: Stack-based Buffer Overflow
- CWE-122: Heap-based Buffer Overflow
- CWE-124: Buffer Underwrite ('Buffer Underflow')
- CWE-125: Out-of-bounds Read
7. 开发安全建议
- 将安全编码规范纳入开发流程
- 对开发人员进行安全编码培训
- 在SDL(安全开发生命周期)中集成缓冲区溢出防护
- 使用现代内存安全语言(Rust等)替代C/C++用于安全敏感组件
8. 工具推荐
-
静态分析工具:
- 360代码卫士
- Coverity
- Fortify
- Klocwork
-
动态分析工具:
- AddressSanitizer(ASan)
- Valgrind
- Dr. Memory
-
模糊测试工具:
- AFL
- libFuzzer
- Honggfuzz
附录:常见易受攻击函数列表
| 不安全函数 | 安全替代方案 |
|---|---|
| gets() | fgets() |
| strcpy() | strncpy() |
| strcat() | strncat() |
| sprintf() | snprintf() |
| scanf() | fgets()+sscanf() |
| vsprintf() | vsnprintf() |
通过全面理解缓冲区下溢的原理、危害和防护措施,开发人员可以有效地在代码中预防此类安全漏洞,提高软件的安全性。