为什么C告诉我这是不安全的,即使我尝试给出正确的输入?使用printf/scanf和%s的漏洞
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char id[8];
printf("Your ID:");
scanf("%s", id);
printf("%s", id);
return 0;
}
我假设,因为它可能会被利用?怎么会这样?
为什么C告诉我这是不安全的,即使我尝试给出正确的输入?使用printf/scanf和%s的漏洞
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char id[8];
printf("Your ID:");
scanf("%s", id);
printf("%s", id);
return 0;
}
我假设,因为它可能会被利用?怎么会这样?
scanf()
没有设置任何界限作为输入,所以很容易溢出你的缓冲区。
现代编译器可能会启用堆栈粉碎检测,所以如果您通过gcc
进行编译而没有设置-fno-stack-protector
标志,程序会故意提前崩溃而不是运行这样一个令人讨厌的错误,而不会被发现。
您最好使用fgets()
,然后使用sscanf()
或其他一些机制来解析输入,这样可以保证丢弃额外的输入。
id
是8个字符长的缓冲区。 scanf("%s", id);
未检查输入字符串的长度。因此,如果用户输入的字符串长度超过7个字符(+1为空终止符),则会溢出分配的缓冲区并破坏程序。如果字符串是以特殊方式制作的,它可能会让黑客获得一些特权,例如执行任意代码。
除了过度运行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);
}
是互联网搜索不工作? – kaylum
如果我将50个字符的字符串作为输入,该怎么办?你只有一个8字节的缓冲区。 – dman2306
如果有人输入超过8个字符,它会覆盖内存,并可能造成灾难性后果。 –