☰
  • 首页
  • 规则分类
  • 项目介绍
search
•••

避免在事务中通过路径多次访问同一文件

16.2 ID_TOCTOU
目录 › next › previous

攻击者可以在两次通过路径访问文件的中途对文件做手脚,从而造成不良后果。

这种问题称为“TOCTOU(Time-of-check to time-of-use)”。有时需要先检查文件的某种状态,如果状态满足条件的话,再使用该文件,如果“检查”和“使用”都是通过路径完成的,攻击者可以在中途将文件替换成不满足条件的文件,如将文件替换成指向另一个文件的链接,从而对系统造成破坏,这是一种典型的“竞态条件”。

示例:

void create(const char* path) {
    FILE* fp = fopen(path, "r");
    if (fp != NULL) {              // #1, time-of-check
        fclose(fp);
        return;
    }
    fp = fopen(path, "w");         // #2, time-of-use, non-compliant
    if (fp != NULL) {
        fwrite("abc", 1, 3, fp);
        fclose(fp);
    }
}

示例代码先通过路径判断文件是否存在,如果存在则不作处理,如果不存在则再次通过路径创建文件并写入数据。如果攻击者把握住时机,在程序执行到 #1 和 #2 之间时按 path 创建指向其他文件的链接,那么被指向的文件会遭到破坏,尤其是当被攻击的进程权限比较高时,破坏力是难以控制的。

应只通过路径打开文件对象一次,只通过文件对象操作文件:

void create(const char* path) {
    FILE* fp = fopen(path, "wx");   // Compliant, since C11
    if (fp != NULL) {
        fwrite("abc", 1, 3, fp);
        fclose(fp);
    }
}

利用“wx”模式即可保证 fopen 在文件不存在时创建文件,文件存在时返回空。

注意,目前 C++ 的 fstream 尚无法完成与“wx”模式相同的功能,相同功能的代码要用 fopen 实现。

依据

ISO/IEC 9899:1999 7.19.5.3(3) ISO/IEC 9899:2011 7.21.5.3(3)

参考

CWE-367
Copyright©2024 360 Security Technology Inc., Licensed under the Apache-2.0 license.