使用 printf/scanf 和 %s 的漏洞

TRX*_*TRX 0 c printf scanf

为什么即使我尝试提供正确的输入,C 也会告诉我这是不安全的?

#include <stdio.h> 
#include <stdlib.h>

int main(void) {
    char id[8];

    printf("Your ID:");
    scanf("%s", id);

    printf("%s", id);

    return 0; 
}
Run Code Online (Sandbox Code Playgroud)

我假设是因为它可以被利用?为何如此?

Clo*_*oud 5

scanf()不会对作为输入的内容设置任何界限,因此很容易溢出id[]缓冲区。

现代编译器可能会启用堆栈粉碎检测,因此如果您在gcc不设置-fno-stack-protector标志的情况下编译通过,程序将故意提前崩溃,而不是运行时没有注意到这种令人讨厌的错误。

你最好使用fgets()然后sscanf()或其他一些机制来解析输入,这样你就可以保证额外的输入被丢弃。


chu*_*ica 5

除了id[]数据过多导致超跑之外,还有一个漏洞:
不检查输入函数的返回值。

用户可以关闭stdin导致scanf("%s", id)返回EOF并且不放入任何内容id[]。然后,以下代码printf("%s", id);尝试打印未初始化的缓冲区。

char id[8];
scanf("%s", id);  // Bad, return value not checked.
printf("%s", id);

// Better
if (1 == scanf("%7s", id)) {
  printf("%s", id);
}

// even better
if (fgets(id, sizeof id, stdin)) {
  id[strcspn(id, "\n")] = '\0'; // lop off potential \n
  printf("%s", id);
}
Run Code Online (Sandbox Code Playgroud)