Why is strncpy insecure?

2019-01-01 09:13发布

问题:

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?

回答1:

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.



回答2:

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.



回答3:

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.



回答4:

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.



回答5:

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.