为什么 strncpy 不安全?

发布于 2024-07-21 08:24:56 字数 58 浏览 7 评论 0原文

我想找出为什么 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

最初的梦 2024-07-28 08:24:56

看看此网站; 这是一个相当详细的解释。 基本上,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.

给妤﹃绝世温柔 2024-07-28 08:24:56

最初的问题显然是 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.

无需解释 2024-07-28 08:24:56

要安全地使用 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.

一桥轻雨一伞开 2024-07-28 08:24:56

该问题基于“已加载”前提,这使得问题本身无效。

这里的底线是 strncpy 不被认为是不安全的,并且从未被认为是不安全的。 唯一可以附加到该函数的“不安全”声明是 C 内存模型和 C 语言本身普遍不安全的广泛声明。 (但这显然是一个完全不同的话题)。

在 C 语言领域,对 strncpy 固有的某种“不安全性”的错误信念源于使用 strncpy 进行“安全字符串复制”的广泛可疑模式,即该函数不执行并且从未打算执行的操作。 这样的用法确实很容易出错。 但即使你在“高度容易出错”和“不安全”之间加上等号,它仍然是一个使用问题(即缺乏教育问题)而不是一个 strncpy 问题。

基本上,可以说 strncpy 的唯一问题是一个不幸的命名,这使得新手程序员认为他们了解这个函数的作用,而不是实际阅读规范。 看着函数名称,不称职的程序员会假设 strncpystrcpy 的“安全版本”,而实际上这两个函数完全不相关。

例如,可以对除法运算符提出完全相同的主张。 大多数人都知道,关于 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 using strncpy 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 a strncpy 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 that strncpy is a "safe version" of strcpy, 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 to 0.5 but I got 0 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 what strncpy actually does. It takes time to learn that strncpy is a conversion function, intended for converting zero-terminated strings to fixed-width strings. It takes time to learn that strncpy 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 against strncpy.

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 of strcpy. It is not in any way intended to claim that strncpy itself is somehow insecure.

夜声 2024-07-28 08:24:56

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 日)

banned.h:将strcat()标记为禁止

strcat() 函数具有与 strcpy() 相同的溢出问题。
另外,很容易意外地出现二次方,因为每个后续调用都必须遍历现有字符串。

最后一次 strcat() 调用在 f063d38(守护进程:使用
重新生成时 cld->env_array,2015-09-24,Git 2.7.0)。
一般来说,strcat() 可以替换为动态字符串
strbufxstrfmt),或者如果您知道长度是有限的,则使用 xsnprintf


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)

banned.h: mark strcat() as banned

The strcat() function has all of the same overflow problems as strcpy().
And as a bonus, it's easy to end up accidentally quadratic, as each subsequent call has to walk through the existing string.

The last strcat() call went away in f063d38 (daemon: use
cld->env_array when re-spawning, 2015-09-24, Git 2.7.0).
In general, strcat() can be replaced either with a dynamic string
(strbuf or xstrfmt), or with xsnprintf if you know the length is bounded.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文