strcpy,gets等功能是否总是危险的?如果我写这样的代码怎么办?
int main(void)
{
char *str1 = "abcdefghijklmnop";
char *str2 = malloc(100);
strcpy(str2, str1);
}
这样函数不接受参数(参数...),并且str变量总是相同的长度...这里是16或稍微多一些,具体取决于编译器版本......但是100将会足以满足2011年3月的行动:)。 有没有办法让黑客利用上面的代码? 10倍!
答案 0 :(得分:13)
绝对不是。与Microsoft marketing campaign的非标准功能相反,strcpy
在正确使用时是安全的。
以上是多余的,但大多数都是安全的。唯一可能的问题是您没有检查malloc
返回值,因此您可能正在取消引用null(如kotlinski所指出的)。在实践中,这可能会立即导致SIGSEGV和程序终止。
使用不当和危险的是:
char array[100];
// ... Read line into uncheckedInput
// Extract substring without checking length
strcpy(array, uncheckedInput + 10);
这是不安全的,因为strcpy可能会溢出,导致未定义的行为。实际上,这很可能会覆盖其他局部变量(本身就是一个主要的安全漏洞)。其中一个可能是返回地址。通过return to lib C攻击,攻击者可以使用system
之类的C函数来执行任意程序。溢出还有其他可能的后果。
但是,gets
确实本质上不安全,并将从下一版本的C(C1X)中删除。根本没有办法确保输入不会溢出(导致上面给出的相同后果)。有些人认为与已知输入文件一起使用时是安全的,但实际上没有理由使用它。 POSIX的getline
是一个更好的选择。
此外,str1
的长度不会因编译器而异。它应该总是17,包括终止NUL。
答案 1 :(得分:5)
char * str1 =“abcdefghijklmnop”;
{这里插入了足够多的行,以便str1和str2不会在屏幕上相互靠近}}
char * str2 = malloc(100); strcpy(str2,str1);
}
此时,有人会将str1更改为
str1 =“这是一个非常长的线索,现在将超过任何缓冲区用于复制,除非预先检查弦的限制。并且很少有人记得在这个问题上存在问题5岁的BUGGY计划“
并忘记查看str1的使用位置,然后随机错误将开始发生...
答案 2 :(得分:4)
你有力地把完全不同的东西塞进一个类别。
函数gets
确实总是很危险。无论你愿意采取什么步骤以及你愿意采取多少防御措施,都无法安全地拨打gets
。
如果您愿意采取[简单]必要步骤以确保拨打strcpy
安全,那么功能strcpy
绝对安全。
这已经将gets
和strcpy
置于极为不同的类别中,这些类别在安全方面没有任何共同之处。
针对strcpy
的安全方面的流行批评完全基于轶事社会观察而非正式事实,例如“程序员很懒惰,不称职,所以不要让他们使用strcpy
”。在C编程的背景下,这当然是完全无稽之谈。遵循这个逻辑,我们也应该完全相同的原因声明除法运算符完全不安全。
实际上,strcpy
无任何问题。另一方面,gets
是一个完全不同的故事,正如我上面所说的那样。
答案 3 :(得分:1)
strcpy
就没有危险;否则strcpy
会愉快地复制比你的目标缓冲区所能容纳的更多字符,这可能会导致一些不幸的后果(堆栈/其他变量覆盖,这可能导致崩溃,堆栈粉碎攻击& co。)。
但是:如果您在输入中有一个尚未检查的通用char *
,唯一可以确定的方法是将strlen
应用于此类字符串并检查它是否对您来说太大了缓冲;但是,现在你必须遍历整个源字符串两次,一次用于检查其长度,一次用于执行复制。
这是次优的,因为如果strcpy
稍微提高一点,它可以接收缓冲区大小的参数,如果源字符串太长则停止复制;在一个完美的世界中,这就是strncpy
的表现(遵循其他strn***
函数的模式)。但是,这不是一个完美的世界,而strncpy
并非旨在实现此目的。相反,非标准(但很受欢迎)的替代方案是strlcpy
,它不会超出目标缓冲区的范围,而是截断。
有几个CRT实现不提供此功能(特别是glibc),但您仍然可以获得其中一个BSD实现并将其放入您的应用程序中。标准(但较慢)的替代方法可以是使用snprintf
和"%s"
作为格式字符串。
那就是说,既然你是用C ++编程的( 编辑 我现在看到C ++标签已被删除了),你为什么不避免所有的C字符串废话(显然你可以)和std::string
一起去?所有这些潜在的安全问题都消失了,字符串操作变得更加容易。
答案 4 :(得分:1)
malloc可能失败的唯一方法是发生内存不足错误,这本身就是一场灾难。您无法从中可靠地恢复,因为几乎任何东西都可能再次触发它,并且操作系统可能会终止您的进程。
答案 5 :(得分:0)
您的代码不安全。 malloc
的返回值未选中,如果失败并返回0,strcpy
将给出未定义的行为。
除此之外,我认为除了示例基本上没有做任何事情之外没有任何问题。
答案 6 :(得分:0)
正如您所指出的,在有限的情况下,strcpy并不危险。更典型的做法是接受一个字符串参数并将其复制到本地缓冲区,这就是当事情变得危险并导致缓冲区溢出时。只需记住在调用strcpy之前检查你的拷贝长度,然后在null之后终止字符串。
答案 7 :(得分:0)
除了潜在的解除引用NULL(因为你不检查来自malloc的结果)是UB并且可能不是安全威胁之外,没有潜在的安全问题。
答案 8 :(得分:0)
gets()
始终不安全;其他功能可以安全使用
即使您完全控制输入,gets()
也是不安全的 - 有一天,该程序可能由其他人运行。
使用gets()
的唯一安全方法是将它用于单个运行的东西:创建源;编译;跑;删除二进制文件和源文件;解释结果。