这是我在一本关于计算机安全的书中发现的问题。它显示了一个代码,但没有解释为什么它是危险的。
你能解释一下吗?
问题在于:
#include <stdlib.h>
#include <string.h>
void f (char *s)
{
char buf[32];
strcpy (buf, s);
}
int main (int argc, char **argv)
{
volatile int i = 0;
if (argc> 1)
f (argv[1]);
if (i)
system ("/bin/sh");
return EXIT_SUCCESS;
}
感谢您的回答!
答案 0 :(得分:3)
函数strcpy
不检查它写入的缓冲区的边界,因此如果要复制的字符串太大而导致缓冲区导致未定义的行为甚至程序崩溃,则可能会溢出。您应该使用更安全的替代strncpy
。它限制了要复制的字节数。
void f(char *s) {
char buf[32]; // can be a variable length array
strncpy(buf, s, (sizeof buf) - 1); // copy at most 31 bytes
buf[31] = '\0'; // make buf a string just in case strlen(s) > 31
}
如果s
指向的缓冲区中的前32个字节中没有空字节,则buf
将不会以空值终止,并且{{1}将复制所有32个字节}。因此,如果你想让buf成为一个字符串,那么你应该为空字节留一个位置并将它放在strncpy
的末尾。
答案 1 :(得分:1)
函数f
将传递给程序的第一个参数的内容复制到缓冲区中,但使用不执行任何边界检查的strcpy
。因此,您可以执行缓冲区溢出攻击并覆盖i
变量的值,这将导致程序产生shell提示符。
自己尝试一下 - 只需使用超过32个字符的参数调用程序。
要比较strcpy
和strncpy
哪个更安全,请参阅their manual page
答案 2 :(得分:1)
这段代码很危险,因为这行:
strcpy (buf, s);
该行正在尝试将传递的字符串复制到长度为32的缓冲区中。但是,我们没有设置复制时间长度或输入字符串s
的长度。这就是所谓的缓冲区溢出。因此,任意数据(如执行“邪恶”命令的字符串)都可以放入内存中。
例如,如果我使用一个由32个空格组成的字符串,然后将字符串“/ bin / sh -c rm -rf /”设置为s
,那么该函数可能会意外删除您的硬盘! (从技术上讲,你需要成为管理员才能工作,但这个例子很有效)
要修复它,请改用strncpy
,这需要额外的参数,即要复制的长度。这将使我们危险的代码行安全:
strncpy(buf, s, 32);