strcpy函数总是危险的吗?
strcpy、get等函数是否总是危险的?如果我写这样的代码会怎么样:strcpy函数总是危险的吗?,c,security,C,Security,strcpy、get等函数是否总是危险的?如果我写这样的代码会怎么样: int main(void) { char *str1 = "abcdefghijklmnop"; char *str2 = malloc(100); strcpy(str2, str1); } int main(void) { char *str1 = "abcdefghijklmnop"; {enough lines have been inserted here so as to not have str
int main(void)
{
char *str1 = "abcdefghijklmnop";
char *str2 = malloc(100);
strcpy(str2, 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);
}
这样,函数不接受参数(参数…),str变量的长度将始终相同…根据编译器版本的不同,这里的长度为16或稍长一些…但是从2011年3月起,yeah 100就足够了:)。
黑客有没有办法利用上面的代码?
10倍 您的代码不安全。
malloc
的返回值未选中,如果失败并返回0,strcpy
将给出未定义的行为
除此之外,我认为没有问题,除了这个例子基本上没有任何作用。绝对没有。与微软的非标准功能不同,
strcpy
在正确使用时是安全的
以上是多余的,但大多是安全的。唯一的潜在问题是您没有检查malloc
返回值,因此您可能正在取消对null的引用(正如kotlinski所指出的)。实际上,这可能导致SIGSEGV和程序立即终止
不适当和危险的使用是:
char array[100];
// ... Read line into uncheckedInput
// Extract substring without checking length
strcpy(array, uncheckedInput + 10);
这是不安全的,因为strcpy可能溢出,导致未定义的行为。实际上,这可能会覆盖其他局部变量(本身就是一个重大的安全漏洞)。其中一个可能是回信地址。通过攻击,攻击者可以使用C函数(如system
)执行任意程序。溢流还有其他可能的后果
但是,它确实本质上是不安全的,并且将从下一版本的C(C1X)中删除。根本没有办法确保输入不会溢出(造成上述相同的后果)。有些人会争辩说,当与已知的输入文件一起使用时,它是安全的,但实际上没有理由使用它。POSIX是一个更好的选择
而且,
str1
的长度不会因编译器而异。它应该始终为17,包括终止NUL。正如您所指出的,在受约束的情况下,strcpy并不危险。更典型的做法是接收一个字符串参数并将其复制到本地缓冲区,在这种情况下,事情可能变得危险并导致缓冲区溢出。只需记住在调用strcpy之前检查副本长度,null在调用后终止字符串。除了可能取消对null的引用(因为您没有检查malloc的结果),null是UB,可能不会造成安全威胁,这不存在潜在的安全问题。您将完全不同的内容强行塞入一个类别中
函数获取
确实总是危险的。无论您愿意采取什么步骤,以及您愿意采取的防御措施如何,都无法安全地调用get
如果您愿意采取[简单]必要的步骤来确保对strcpy
的调用是安全的,那么函数strcpy
是完全安全的
这已经将获取
和strcpy
分为截然不同的类别,在安全方面没有任何共同之处
针对strcpy安全方面的流行批评完全基于轶事式的社会观察,而不是形式上的事实,例如,“程序员懒惰无能,所以不要让他们使用strcpy”。在C编程的环境中,这当然是胡说八道。按照这个逻辑,我们还应该声明除法运算符完全不安全,原因完全相同
实际上,strcpy
没有任何问题<另一方面,代码>获取,是一个完全不同的故事,正如我上面所说的 get()
总是不安全的;其他功能可以安全使用。gets()
即使在您完全控制输入时也是不安全的——有朝一日,程序可能会由其他人运行
使用
get()
的唯一安全方法是将其用于一次运行:创建源代码;编撰;跑删除二进制文件和源文件;解释结果。strcpy
据您所知,目标缓冲区足够大,可以容纳源字符串的字符,因此并不危险;否则,strcpy
会很高兴地复制比目标缓冲区所能容纳的字符更多的字符,这可能会导致一些不幸的后果(堆栈/其他变量覆盖,这可能导致崩溃、堆栈崩溃攻击等)
但是:如果您的输入中有一个通用的char*
,但尚未检查,唯一可以确保的方法是将strlen
应用于此类字符串,并检查它是否对您的缓冲区太大;但是,现在必须遍历整个源字符串两次,一次用于检查其长度,一次用于执行复制
这是次优的,因为如果strcpy稍微高级一点,它可以接收缓冲区大小作为参数,如果源字符串太长,则停止复制;在一个完美的世界中,strncpy
就是这样执行的(遵循其他strn***
函数的模式)。然而,这并不是一个完美的世界,strncpy
并不是为实现这一点而设计的。取而代之的是,非标准(但很流行)的替代方法是截断,而不是超出目标缓冲区的界限
一些CRT实现不提供此功能(特别是glibc),但您仍然可以获得一个BSD实现并将其放入应用程序中。一个标准的(但较慢的)替代方法是使用snprintf
和%s”
作为格式字符串
这是因为,你在C++中编程(<强>编辑< /强>我现在看到C++标签已经被删除了),为什么你不只是避开所有的C字符串废话(显然是可以的),然后跟着<代码> STD::String >?所有的