为什么strncpy不安全?
我正在寻找为什么strncpy被认为是不安全的。 有没有人有这样的文件或利用它的例子?
看看这个网站 ; 这是一个相当详细的解释。 基本上, strncpy()
不需要NUL终止,因此易受各种漏洞攻击。
原来的问题很明显, strcpy(3)不是一个内存安全的操作 ,所以攻击者可以提供比缓冲区更长的string来覆盖堆栈上的代码,如果仔细安排,可以执行攻击者的任意代码。
但是strncpy(3)还有另外一个问题,就是在目的地的每一种情况下它都不提供空终止。 (假设一个源string比目标缓冲区长。)未来的操作可能期望在相同大小的缓冲区之间符合C nul终止的string,并在结果复制到第三个缓冲区时在下游发生故障。
使用strncpy(3)比strcpy(3)更好,但是strclpy(3)更好。
为了安全地使用strncpy,必须(1)手动将空字符粘贴到结果缓冲区上,(2)知道缓冲区事先以null结束,并且将(长度-1)传递给strncpy,或者(3)知道永远不会使用任何不会将其长度限制在缓冲区长度的方法来复制缓冲区。
需要注意的是,strncpy将填充缓冲区中的所有内容到复制的string中,而其他长度受限的strcpy变体则不会。 在某些情况下,这可能会导致性能下降,但在其他情况下则是安全优势。 例如,如果使用strlcpy将“supercalifragilisticexpalidocious”复制到缓冲区中,然后复制“缓冲区”,则缓冲区将保持“它”ercalifragilisticexpalidocious ^“(使用”^“来表示零字节)。 如果缓冲区被复制到一个固定大小的格式,额外的数据可能会与它一起标记。
问题是基于一个“加载”的前提,这使得问题本身是无效的。
这里的底线是strncpy
不被认为是不安全的,从来没有被认为是不安全的。 可以附加在这个function上的“不安全”的唯一主张是C存储器模型和C语言本身的广义不安全性。 (但这显然是一个完全不同的话题)。
在C语言领域内, strncpy
固有的某种“不安全”的错误信念源自于使用strncpy
进行“安全string复制”的广泛可疑模式,也就是这个函数没有做的也从未打算过的东西。 这样的用法确实是非常容易出错的。 但即使你把“高度容易出错”和“不安全”之间的平等标志放在一起,它仍然是一个使用问题(即缺乏教育问题)而不是一个strncpy
问题。
基本上,可以说strncpy
的唯一问题是一个不幸的命名,这使得新手程序员假定他们理解这个函数做什么,而不是实际阅读规范。 看一个不称职的程序员的函数名称,假定strncpy
是strcpy
的“安全版本”,而实际上这两个函数是完全不相关的。
举一个例子,可以针对划分运算符提出完全相同的要求。 正如你们大多数人所知道的,关于C语言的最常见的问题之一是“我认为1/2
会评估为0.5
但我得到了0
为什么呢?” 但是,我们并不认为分工运营商是不安全的,因为语言初学者往往会误解其行为。
再举一个例子,我们不把伪随机数发生器函数称为“不安全”,只是因为无能的程序员通常不满意它们的输出并不是真正随机的。
这正是如何与strncpy
函数。 就像初学程序员需要花时间学习伪随机数生成器实际上做什么一样,需要花时间来学习strncpy
实际上做了什么。 学习strncpy
是一个转换函数需要花费时间,该函数旨在将零终止的string转换为固定宽度的string。 学习strncpy
与“安全string复制”完全无关,需要时间才能达到目的。
诚然,语言strncpy
通常需要更长的时间才能学习strncpy
的目的,而不是与分裂运算符一起解决问题。 但是,这是任何“不安全”索赔的基础。
PS在接受的答案中链接的CERT文档专门用来说明:为了certificatestrncpy
函数作为strcpy
的“安全”版本的典型无能滥用的不安全性。 这绝不是要声称strncpy
本身在某种程度上是不安全的。
当源缓冲区和目标缓冲区相互重叠时,会出现最糟糕的情况。 所以当你感觉到程序中可能会出现重叠的情况时,避免使用strncpy。 而不是strncpy,你可以在重叠的场景中使用memmove函数。
在下面我正在描述一个简单的例子,它描述了重叠场景中的strncpy。
#include <stdio.h> #include <string.h> int main() { char aszMessage[10] ="12345"; //Source Buffer short siLen=4; // Length of byte you want to copy strncpy(aszMessage + 2,aszMessage+1,siLen);//Here memory overlap printf("\n\n\tMessage = %s\n",aszMessage); return 0; }
在这里我接受,输出应该是122345,但是这里的输出是122222,这是strncpy最大的回退场景。
这个问题可以通过使用memove函数来解决。
#include <stdio.h> #include <string.h> int main() { char aszMessage[10] ="12345"; //Source Buffer short siLen=4; // Length of byte you want to copy memmove(aszMessage + 2,aszMessage+1,siLen);//Here memory overlap printf("\n\n\tMessage = %s\n",aszMessage); return 0; }
现在我得到了欲望输出122345。
欲了解更多详情,你可以看到这个链接http://aticleworld.com/how-to-use-strncpy-and-how-to-write-your-own-strncpy/