【缺陷周话】第15期----资源未释放:文件
字数 1377 2025-08-18 11:37:49

资源未释放:文件缺陷详解与防护指南

1. 缺陷概述

资源未释放:文件是指在使用文件、IO流等资源时,未能及时关闭或释放已打开的文件描述符,导致系统资源泄露的安全缺陷。这类缺陷属于CWE-775: Missing Release of File Descriptor or Handle after Effective Lifetime。

关键特性:

  • 文件操作的基本流程包括:打开、读写、删除、关闭
  • 虽然程序退出时会自动关闭打开的文件,但依赖此机制存在风险
  • 每个程序同时打开的文件数量有限制(≤FOPEN_MAX)

2. 危害分析

文件描述符未释放可能导致:

  1. 信息泄露:敏感文件可能被未授权的进程访问
  2. 拒绝服务(DoS):文件描述符耗尽导致系统无法处理新请求
  3. 系统性能下降:资源浪费影响整体性能

实际漏洞案例:

  • CVE-2018-14621:libtirpc中的无限循环漏洞,文件描述符耗尽导致服务器拒绝服务
  • CVE-2018-9275:Yubico PAM模块中的文件描述符泄露,导致信息泄露和DoS攻击

3. 缺陷代码示例与分析

3.1 缺陷代码

#include <stdio.h>

void badSink(FILE * data)
{
    /* FLAW: No attempt to close the file */
    ; /* empty statement needed for some flow variants */
}

void bad()
{
    FILE * data;
    data = fopen("CWE775_Missing_Release_of_File_Descriptor__fopen_no_close_01_bad.txt", "w+");
    badSink(data);
}

问题点

  • 第26行使用fopen()打开文件
  • 函数结束前未调用fclose()释放资源
  • 文件描述符会一直保持打开状态

3.2 修复代码

#include <stdio.h>

void goodSink(FILE * data)
{
    /* FIX: If the file is still opened, close it */
    if (data != NULL)
    {
        fclose(data);
    }
}

void good()
{
    FILE * data;
    data = fopen("CWE775_Missing_Release_of_File_Descriptor__fopen_no_close_01_good.txt", "w+");
    goodSink(data);
}

修复要点

  • 第30行显式调用fclose()关闭文件
  • 添加NULL检查确保指针有效
  • 确保资源在任何执行路径下都能被释放

4. 检测与防护措施

4.1 防护建议

  1. 及时手动关闭

    • 文件使用完毕后立即调用fclose()
    • 对于C++,使用RAII模式管理文件资源
  2. 异常处理

    • 在所有异常处理分支中添加资源释放代码
    • 使用try-finally或类似机制确保资源释放
  3. 最佳实践

    • 将资源获取与释放放在同一抽象层次
    • 使用智能指针或资源管理类自动处理释放
  4. 代码审查

    • 检查所有文件操作是否配对出现open/close
    • 特别注意错误处理路径中的资源释放

4.2 自动化检测

使用静态代码分析工具(如360代码卫士)可以:

  • 自动识别未配对的资源操作
  • 检测异常路径中的资源泄露
  • 提供缺陷定位和修复建议

5. 扩展知识

相关CWE条目:

  • CWE-775: Missing Release of File Descriptor or Handle after Effective Lifetime
  • CWE-404: Improper Resource Shutdown or Release
  • CWE-772: Missing Release of Resource after Effective Lifetime

编程语言差异:

  • C/C++:需要显式调用fclose()
  • Java:使用try-with-resources或显式调用close()
  • Python:使用with语句或显式调用close()
  • C#:使用using语句或显式调用Dispose()

6. 总结

文件资源未释放是常见但容易被忽视的安全缺陷,开发者应当:

  1. 建立资源管理的规范意识
  2. 在所有代码路径中确保资源释放
  3. 利用自动化工具辅助检测
  4. 在代码审查中特别关注资源管理

通过规范的编码实践和工具辅助,可以有效预防此类缺陷,提高软件的安全性和可靠性。

资源未释放:文件缺陷详解与防护指南 1. 缺陷概述 资源未释放:文件 是指在使用文件、IO流等资源时,未能及时关闭或释放已打开的文件描述符,导致系统资源泄露的安全缺陷。这类缺陷属于CWE-775: Missing Release of File Descriptor or Handle after Effective Lifetime。 关键特性: 文件操作的基本流程包括:打开、读写、删除、关闭 虽然程序退出时会自动关闭打开的文件,但依赖此机制存在风险 每个程序同时打开的文件数量有限制(≤FOPEN_ MAX) 2. 危害分析 文件描述符未释放可能导致: 信息泄露 :敏感文件可能被未授权的进程访问 拒绝服务(DoS) :文件描述符耗尽导致系统无法处理新请求 系统性能下降 :资源浪费影响整体性能 实际漏洞案例: CVE-2018-14621 :libtirpc中的无限循环漏洞,文件描述符耗尽导致服务器拒绝服务 CVE-2018-9275 :Yubico PAM模块中的文件描述符泄露,导致信息泄露和DoS攻击 3. 缺陷代码示例与分析 3.1 缺陷代码 问题点 : 第26行使用 fopen() 打开文件 函数结束前未调用 fclose() 释放资源 文件描述符会一直保持打开状态 3.2 修复代码 修复要点 : 第30行显式调用 fclose() 关闭文件 添加NULL检查确保指针有效 确保资源在任何执行路径下都能被释放 4. 检测与防护措施 4.1 防护建议 及时手动关闭 : 文件使用完毕后立即调用 fclose() 对于C++,使用RAII模式管理文件资源 异常处理 : 在所有异常处理分支中添加资源释放代码 使用 try-finally 或类似机制确保资源释放 最佳实践 : 将资源获取与释放放在同一抽象层次 使用智能指针或资源管理类自动处理释放 代码审查 : 检查所有文件操作是否配对出现 open/close 特别注意错误处理路径中的资源释放 4.2 自动化检测 使用静态代码分析工具(如360代码卫士)可以: 自动识别未配对的资源操作 检测异常路径中的资源泄露 提供缺陷定位和修复建议 5. 扩展知识 相关CWE条目: CWE-775: Missing Release of File Descriptor or Handle after Effective Lifetime CWE-404: Improper Resource Shutdown or Release CWE-772: Missing Release of Resource after Effective Lifetime 编程语言差异: C/C++ :需要显式调用 fclose() Java :使用 try-with-resources 或显式调用 close() Python :使用 with 语句或显式调用 close() C# :使用 using 语句或显式调用 Dispose() 6. 总结 文件资源未释放是常见但容易被忽视的安全缺陷,开发者应当: 建立资源管理的规范意识 在所有代码路径中确保资源释放 利用自动化工具辅助检测 在代码审查中特别关注资源管理 通过规范的编码实践和工具辅助,可以有效预防此类缺陷,提高软件的安全性和可靠性。