【缺陷周话】第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导致下溢

问题点

  1. 使用固定大小的缓冲区(dataBadBuffer)存储可能超长的数据
  2. 使用不安全的strcpy()函数而没有长度检查
  3. 目的缓冲区(dataBadBuffer)小于源缓冲区(source)

4.2 修复代码示例

char * data;
char dataBadBuffer[10];
char dataGoodBuffer[10+1];
strcpy(dataGoodBuffer, "AAAAAAAAAA"); // 10个A
data = dataGoodBuffer;  // 指向11字节的缓冲区
strcpy(data, source);   // 现在缓冲区足够大

修复方法

  1. 确保目的缓冲区足够大(dataGoodBuffer[10+1])
  2. 仍然建议使用更安全的函数替代strcpy()

5. 检测与防护措施

5.1 检测方法

  • 静态代码分析工具(如360代码卫士)
  • 动态运行时检测
  • 代码审查重点关注:
    • 不安全的字符串操作函数(strcpy, strcat等)
    • 固定大小的缓冲区
    • 缺少边界检查的循环

5.2 防护措施

5.2.1 编码实践

  1. 避免使用不安全函数

    • 用strncpy()替代strcpy()
    • 用snprintf()替代sprintf()
    • 用fgets()替代gets()
  2. 边界检查

    if(strlen(source) < sizeof(dest)) {
        strncpy(dest, source, sizeof(dest)-1);
        dest[sizeof(dest)-1] = '\0';
    }
    
  3. 使用安全字符串库

    • 如Safe C Library、Microsoft的STRSAFE库
  4. 编译器选项

    • 开启栈保护(-fstack-protector)
    • 启用堆栈不可执行(DEP/NX)
    • 地址空间布局随机化(ASLR)

5.2.2 防御性编程

  1. 始终假设输入可能是恶意的
  2. 对来自外部的所有数据进行严格验证
  3. 使用自动化工具进行定期代码审计

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. 开发安全建议

  1. 将安全编码规范纳入开发流程
  2. 对开发人员进行安全编码培训
  3. 在SDL(安全开发生命周期)中集成缓冲区溢出防护
  4. 使用现代内存安全语言(Rust等)替代C/C++用于安全敏感组件

8. 工具推荐

  1. 静态分析工具

    • 360代码卫士
    • Coverity
    • Fortify
    • Klocwork
  2. 动态分析工具

    • AddressSanitizer(ASan)
    • Valgrind
    • Dr. Memory
  3. 模糊测试工具

    • AFL
    • libFuzzer
    • Honggfuzz

附录:常见易受攻击函数列表

不安全函数 安全替代方案
gets() fgets()
strcpy() strncpy()
strcat() strncat()
sprintf() snprintf()
scanf() fgets()+sscanf()
vsprintf() vsnprintf()

通过全面理解缓冲区下溢的原理、危害和防护措施,开发人员可以有效地在代码中预防此类安全漏洞,提高软件的安全性。

缓冲区下溢漏洞分析与防护指南 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 缺陷代码示例 问题点 : 使用固定大小的缓冲区(dataBadBuffer)存储可能超长的数据 使用不安全的strcpy()函数而没有长度检查 目的缓冲区(dataBadBuffer)小于源缓冲区(source) 4.2 修复代码示例 修复方法 : 确保目的缓冲区足够大(dataGoodBuffer[ 10+1 ]) 仍然建议使用更安全的函数替代strcpy() 5. 检测与防护措施 5.1 检测方法 静态代码分析工具(如360代码卫士) 动态运行时检测 代码审查重点关注: 不安全的字符串操作函数(strcpy, strcat等) 固定大小的缓冲区 缺少边界检查的循环 5.2 防护措施 5.2.1 编码实践 避免使用不安全函数 : 用strncpy()替代strcpy() 用snprintf()替代sprintf() 用fgets()替代gets() 边界检查 : 使用安全字符串库 : 如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() | 通过全面理解缓冲区下溢的原理、危害和防护措施,开发人员可以有效地在代码中预防此类安全漏洞,提高软件的安全性。