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