为什么 strncpy 不安全?
我想找出为什么 strncpy 被认为是不安全的。 有人有任何关于此的文档或使用它的漏洞利用示例吗?
I am looking to find out why strncpy is considered insecure. Does anybody have any sort of documentation on this or examples of an exploit using it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
看看此网站; 这是一个相当详细的解释。 基本上,strncpy() 不需要 NUL 终止,因此容易受到各种攻击。
Take a look at this site; it's a fairly detailed explanation. Basically,
strncpy()
doesn't require NUL termination, and is therefore susceptible to a variety of exploits.最初的问题显然是 strcpy(3) 不是 内存安全操作,因此攻击者可以提供比缓冲区长的字符串,从而覆盖堆栈上的代码,如果精心安排,可以执行攻击者的任意代码。
但是 strncpy(3) 还有另一个问题,它不提供在目的地的每种情况下都为空终止。 (想象一个源字符串比目标缓冲区长。)未来的操作可能会期望大小相同的缓冲区之间存在一致的 C nul 终止字符串,并且当结果复制到第三个缓冲区时下游会发生故障。
使用 strncpy(3) 比 strcpy(3) 更好,但像 strlcpy(3) 这样的东西更好。
The original problem is obviously that strcpy(3) was not a memory-safe operation, so an attacker could supply a string longer than the buffer which would overwrite code on the stack, and if carefully arranged, could execute arbitrary code from the attacker.
But strncpy(3) has another problem in that it doesn't supply null termination in every case at the destination. (Imagine a source string longer than the destination buffer.) Future operations may expect conforming C nul-terminated strings between equally sized buffers and malfunction downstream when the result is copied to yet a third buffer.
Using strncpy(3) is better than strcpy(3) but things like strlcpy(3) are better still.
要安全地使用 strncpy,必须 (1) 手动将空字符粘贴到结果缓冲区上,(2) 事先知道缓冲区以空结尾,并将 (length-1) 传递给 strncpy,或者 (3) 知道永远不会使用任何不会将其长度绑定到缓冲区长度的方法来复制缓冲区。
需要注意的是,strncpy 会将缓冲区中复制的字符串之后的所有内容填零,而其他长度限制的 strcpy 变体则不会。 在某些情况下,这可能会消耗性能,但在其他情况下,这可能会带来安全优势。 例如,如果使用 strlcpy 将“supercalifragilisticexpalidocious”复制到缓冲区中,然后复制“it”,则缓冲区将保存“it^ercalifragilisticexpalidocious^”(使用“^”表示零字节)。 如果缓冲区被复制为固定大小的格式,则额外的数据可能会随之标记。
To safely use strncpy, one must either (1) manually stick a null character onto the result buffer, (2) know that the buffer ends with a null beforehand, and pass (length-1) to strncpy, or (3) know that the buffer will never be copied using any method that won't bound its length to the buffer length.
It's important to note that strncpy will zero-fill everything in the buffer past the copied string, while other length-limited strcpy variants will not. This may at some cases be a performance drain, but in other cases be a security advantage. For example, if one used strlcpy to copy "supercalifragilisticexpalidocious" into a buffer and then to copy "it", the buffer would hold "it^ercalifragilisticexpalidocious^" (using "^" to represent a zero byte). If the buffer gets copied to a fixed-sized format, the extra data might tag along with it.
该问题基于“已加载”前提,这使得问题本身无效。
这里的底线是
strncpy
不被认为是不安全的,并且从未被认为是不安全的。 唯一可以附加到该函数的“不安全”声明是 C 内存模型和 C 语言本身普遍不安全的广泛声明。 (但这显然是一个完全不同的话题)。在 C 语言领域,对
strncpy
固有的某种“不安全性”的错误信念源于使用strncpy
进行“安全字符串复制”的广泛可疑模式,即该函数不执行并且从未打算执行的操作。 这样的用法确实很容易出错。 但即使你在“高度容易出错”和“不安全”之间加上等号,它仍然是一个使用问题(即缺乏教育问题)而不是一个strncpy
问题。基本上,可以说 strncpy 的唯一问题是一个不幸的命名,这使得新手程序员认为他们了解这个函数的作用,而不是实际阅读规范。 看着函数名称,不称职的程序员会假设
strncpy
是strcpy
的“安全版本”,而实际上这两个函数完全不相关。例如,可以对除法运算符提出完全相同的主张。 大多数人都知道,关于 C 语言最常见的问题之一是“我假设
1/2
的计算结果为0.5
,但我得到了为什么是 0?” 然而,我们并不能仅仅因为语言初学者容易误解其行为就认为除法运算符是不安全的。
再举个例子,我们不会仅仅因为不称职的程序员经常对它们的输出不是真正随机的事实感到惊讶而称伪随机数生成器函数“不安全”。
这正是
strncpy
函数的原理。 就像初学者程序员需要时间来了解伪随机数生成器的实际用途一样,他们也需要时间来了解strncpy
实际的用途。 需要花一些时间才能了解strncpy
是一个转换函数,旨在将零终止字符串转换为固定宽度 > 字符串。 需要花一些时间才能了解strncpy
与“安全字符串复制”完全无关,并且不能有意义地用于该目的。诚然,对于语言学习者来说,了解 strncpy 的用途通常比使用除法运算符解决问题要花费更长的时间。 然而,这是针对
strncpy
的任何“不安全”主张的基础。PS 已接受答案中链接的 CERT 文档正是致力于此:证明将
strncpy
函数作为strcpy
的“安全”版本的典型无能滥用的不安全性。 它绝不是为了声称 strncpy 本身在某种程度上不安全。The question is based on a "loaded" premise, which makes the question itself invalid.
The bottom line here is that
strncpy
is not considered insecure and has never been considered insecure. The only claims of "insecurity" that can be attached to that function are the broad claims of general insecurity of C memory model and C language itself. (But that is obviously a completely different topic).Within the realm of C language the misguided belief of some kind of "insecurity" inherent in
strncpy
is derived from the widespread dubious pattern of usingstrncpy
for "safe string copying", i.e. something this function does not do and has never been intended for. Such usage is indeed highly error prone. But even if you put an equality sign between "highly error prone" and "insecure", it is still a usage problem (i.e. a lack of education problem) not astrncpy
problem.Basically, one can say that the only problem with
strncpy
is a unfortunate naming, which makes newbie programmers assume that they understand what this function does instead of actually reading the specification. Looking at the function name an incompetent programmer assumes thatstrncpy
is a "safe version" ofstrcpy
, while in reality these two functions are completely unrelated.Exactly the same claim can be made against the division operator, for one example. As most of you know, one of the most frequently-asked questions about C language goes as "I assumed that
1/2
will evaluate to0.5
but I got0
instead. Why?" Yet, we don't claim that the division operator is insecure just because language beginners tend to misinterpret its behavior.For another example, we don't call pseudo-random number generator functions "insecure" just because incompetent programmers are often unpleasantly surprised by the fact that their output is not truly random.
That is exactly how it is with
strncpy
function. Just like it takes time for beginner programmers to learn what pseudo-random number generators actually do, it takes them time to learn whatstrncpy
actually does. It takes time to learn thatstrncpy
is a conversion function, intended for converting zero-terminated strings to fixed-width strings. It takes time to learn thatstrncpy
has absolutely nothing to do with "safe string copying" and can't be meaningfully used for that purpose.Granted, it usually takes much longer for a language student to learn the purpose of
strncpy
than to sort things out with the division operator. However, this is a basis for any "insecurity" claims againststrncpy
.P.S. The CERT document linked in the accepted answer is dedicated to exactly that: to demonstrate the insecurities of the typical incompetent abuse of
strncpy
function as a "safe" version ofstrcpy
. It is not in any way intended to claim thatstrncpy
itself is somehow insecure.Git 2.19(Q3 2018)的pathc发现,很容易误用
strcat()
等系统API函数;strncpy()
; ...并禁止此代码库中的这些功能。请参阅 提交 e488b7a、提交 cc8fdae, 提交1b11b64(2018 年 7 月 24 日),以及提交 c8af66a(2018 年 7 月 26 日) )作者:杰夫·金 (
peff
)。(由 Junio C Hamano --
gitster
-- 合并于 提交 e28daf2,2018 年 8 月 15 日)A pathc of Git 2.19 (Q3 2018) finds that it is too easy to misuse system API functions such as
strcat()
;strncpy()
; ... and forbids those functions in this codebase.See commit e488b7a, commit cc8fdae, commit 1b11b64 (24 Jul 2018), and commit c8af66a (26 Jul 2018) by Jeff King (
peff
).(Merged by Junio C Hamano --
gitster
-- in commit e28daf2, 15 Aug 2018)