strcpy函数是否总是很危险?

问题描述 投票:4回答:9

strcpy,gets等函数是否总是很危险?如果我写这样的代码怎么办:

int main(void)
{

char *str1 = "abcdefghijklmnop";
char *str2 = malloc(100); 
strcpy(str2, str1);


}

这样,该函数不接受参数(parameters ...),并且str变量将始终具有相同的长度...根据编译器版本的不同,此处长度为16或稍长一些...但是是100就足够了截至2011年3月:)。黑客有没有办法利用上面的代码?10倍!

c security
9个回答
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的gets是更好的选择。

此外,getline的长度也不因编译器而异。它应始终为17,包括终止的NUL。


5
投票
是的,这很危险。经过5年的维护,您的代码将如下所示:

getline

那时,有人会去并将str1更改为

str1 =”这是一个非常长的字符串,现在它将超载任何用于复制它的缓冲区,除非要注意检查该字符串的限制。并且只有很少的人可以在5中解决一个问题一年一度的虫族计划”

并且忘记看看在哪里使用了str1,然后随机错误将开始发生...


4
投票
您正在将完全不同的东西塞进一类。

功能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是绝对安全的。

这已经将strcpystrcpy置于截然不同的类别,它们在安全性方面没有共同之处。

gets安全方面的流行批评完全基于轶事社会观察,而不是正式事实,例如“程序员懒惰且无能,所以不要让他们使用strcpy”。当然,在C编程的上下文中,这完全是胡说八道。遵循此逻辑,出于完全相同的原因,我们还应该将除法运算符完全声明为不安全。

实际上,strcpy没有任何问题。另一方面,正如我上文所述,strcpy是一个完全不同的故事。


1
投票
strcpy并不危险,只要您知道目标缓冲区足够大以容纳源字符串的字符即可;否则,gets将快乐地复制超出目标缓冲区可容纳的字符的数量,这可能导致一些不幸的后果(堆栈/其他变量被覆盖,这可能导致崩溃,堆栈粉碎攻击等)。

但是:如果输入中没有检查通用的strcpy,唯一可以确定的方法是将strcpy应用于这样的字符串,并检查它对于缓冲区是否太大;但是,现在您必须遍历整个源字符串两次,一次用于检查其长度,一次用于执行复制。

这是次优的,因为如果char *稍微高级一点,它可以接收缓冲区的大小作为参数,并且如果源字符串太长则停止复制;在理想情况下,这就是strlen的执行方式(遵循其他strcpy功能的模式)。但是,这是一个完美的世界,并且strncpy并非旨在做到这一点。相反,非标准(但很流行)的替代方法是strn***,该替代方法不会超出目标缓冲区的边界,而是会截断。

几个CRT实现不提供此功能(特别是glibc),但是您仍然可以获得其中一种BSD实现并将其放入您的应用程序中。一种标准的(但较慢的)替代方法可以是将strncpystrlcpy用作格式字符串。

就是说,由于您使用C ++编程(

edit

现在我看到C ++标记已被删除),为什么不避免所有的C字符串废话(当您可以,显然)并选择strlcpy吗?所有这些潜在的安全问题都消失了,字符串操作变得更加容易。

1
投票

0
投票

0
投票

0
投票

0
投票
std::string总是不安全的
© www.soinside.com 2019 - 2024. All rights reserved.