strcpy,gets等函数是否总是很危险?如果我写这样的代码怎么办:
int main(void)
{
char *str1 = "abcdefghijklmnop";
char *str2 = malloc(100);
strcpy(str2, str1);
}
这样,该函数不接受参数(parameters ...),并且str变量将始终具有相同的长度...根据编译器版本的不同,此处长度为16或稍长一些...但是是100就足够了截至2011年3月:)。黑客有没有办法利用上面的代码?10倍!
绝对不是。与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的gets
是更好的选择。此外,
getline
的长度也不因编译器而异。它应始终为17,包括终止的NUL。
getline
那时,有人会去并将str1更改为str1 =”这是一个非常长的字符串,现在它将超载任何用于复制它的缓冲区,除非要注意检查该字符串的限制。并且只有很少的人可以在5中解决一个问题一年一度的虫族计划”
并且忘记看看在哪里使用了str1,然后随机错误将开始发生...
功能str1
确实总是很危险。无论您愿意采取什么步骤以及愿意采取何种防御措施,都无法对int main(void)
{
char *str1 = "abcdefghijklmnop";
{enough lines have been inserted here so as to not have str1 and str2 nice and close to each other on the screen}
char *str2 = malloc(100);
strcpy(str2, str1);
}
进行安全呼叫。
如果您愿意采取[简单]必要的步骤来确保对gets
的调用是安全的,则[Function gets
是绝对安全的。
这已经将strcpy
和strcpy
置于截然不同的类别,它们在安全性方面没有共同之处。
gets
安全方面的流行批评完全基于轶事社会观察,而不是正式事实,例如“程序员懒惰且无能,所以不要让他们使用strcpy
”。当然,在C编程的上下文中,这完全是胡说八道。遵循此逻辑,出于完全相同的原因,我们还应该将除法运算符完全声明为不安全。
实际上,strcpy
没有任何问题。另一方面,正如我上文所述,strcpy
是一个完全不同的故事。
strcpy
并不危险,只要您知道目标缓冲区足够大以容纳源字符串的字符即可;否则,gets
将快乐地复制超出目标缓冲区可容纳的字符的数量,这可能导致一些不幸的后果(堆栈/其他变量被覆盖,这可能导致崩溃,堆栈粉碎攻击等)。但是:如果输入中没有检查通用的strcpy
,唯一可以确定的方法是将strcpy
应用于这样的字符串,并检查它对于缓冲区是否太大;但是,现在您必须遍历整个源字符串两次,一次用于检查其长度,一次用于执行复制。
这是次优的,因为如果char *
稍微高级一点,它可以接收缓冲区的大小作为参数,并且如果源字符串太长则停止复制;在理想情况下,这就是strlen
的执行方式(遵循其他strcpy
功能的模式)。但是,这是一个完美的世界,并且strncpy
并非旨在做到这一点。相反,非标准(但很流行)的替代方法是strn***
,该替代方法不会超出目标缓冲区的边界,而是会截断。
几个CRT实现不提供此功能(特别是glibc),但是您仍然可以获得其中一种BSD实现并将其放入您的应用程序中。一种标准的(但较慢的)替代方法可以是将strncpy
与strlcpy
用作格式字符串。
edit
现在我看到C ++标记已被删除),为什么不避免所有的C字符串废话(当您可以,显然)并选择strlcpy
吗?所有这些潜在的安全问题都消失了,字符串操作变得更加容易。std::string
总是不安全的