C/C++ 中的 printf() 如何成为缓冲区溢出漏洞?

信息安全 缓冲区溢出 C C++
2021-09-02 03:55:59

根据我刚刚阅读的一篇文章,由于缓冲区溢出,这些函数printf和被认为是安全漏洞。strcpy我了解它strcpy是如何脆弱的,但有人可能会解释 printf 如何/如果真的脆弱,或者我只是理解错了。

这是文章:https ://www.digitalbond.com/blog/2012/09/06/100000-vulnerabilities/#more-11658

具体片段是:

供应商已经机械地搜索了源代码,并发现了大约 50,000 种具有缓冲区溢出功能的 C 库函数,例如“strcpy()”和“printf()”。

谢谢!

4个回答

通过printf()使用用户提供的参数作为格式字符串(即printf(arg)代替printf("%s", arg). 我经常看到它这样做。由于调用者没有推送额外的参数,%因此可以使用带有一些虚假说明符的字符串来读取堆栈上的任何内容,并且%n可以将一些值写入内存(%n意思是:“下一个参数是一个int *;去那里写数字到目前为止发出的字符数)。

但是,我发现您引用的文章包含一个简单的印刷错误更合理,并且真正的意思是sprintf(),不是printf()

(我也可以争辩说,除了 之外gets(),没有固有的易受攻击的 C 函数;只有需要小心使用的函数所谓的“安全”替换snprintf()实际上并不能解决问题;他们通过替换来隐藏它带有静默截断的缓冲区溢出,噪声较小但不一定更好。)

除了@Tom 的回答,我还想指导您阅读OWASP 代码审查指南,其中突出显示了使用 printf() 的一些问题,以及cs.stackexchange 网站上类似问题的答案

这是一个示例,显示了此溢出如何为您提供帮助。假设您无权访问私有成员(例如 pwd),因此 printf 将帮助您查看此变量的内容

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

struct SecureLogin{
    SecureLogin(const char * login_)
    {
        strcpy(login,login_);
        strcpy(pwd,"ijk");//the user does not see this part of the source code as it is in a DLL
    }
    char login[8];
private:
    char pwd[8];

};


int main() {
    // your code goes here
    SecureLogin log("abc");
    printf("Pwd = %s\n",(&log.login[0])+8);
    // Pass a string address which is the base address of the login
    // field, but add 8 bytes, which skips onto the pwd field (we know
    // login is 8 bytes)
    return 0;
}

输出:

密码 = ijk

一些 printf 指令(即 %n)对在堆栈中找到的地址有副作用,因此即使显式输出被正确实现,打印指令也可能很危险。