Why is strncpy insecure?
Asked Answered
D

5

75

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?

Drysalter answered 15/5, 2009 at 17:16 Comment(13)
It was my understanding that strcpy was unsafe and that strncpy was the safe version of that.Castoff
There's no _s on the name though. Can't be secure without an _s...Weald
If you are using c++, simply don't use it and use std::string.Gustavo
strncpy wasn't designed as a safe version of strcpy, but it's abused for that purpose. See here for an explanation: lysator.liu.se/c/rat/d11.html . Now one could argue whether or not strncpy was designed wrong. History comes as an excuse for the C committee :) If you need a safe version of strcpy, i recommend you to use other functions.Swore
These are all good answers for strncpy vs strcpy but I'm really more interested in strncpy_s.Drysalter
It isn't just insecure, it was a bad design in the first place to not guarantee that the result was nul terminated.Saucer
@stimms: When you say you're "more interested in strncpy_s", do you mean how strncpy_s() can be insecure, or why strncpy() is insecure as compared to strncpy_s()? strncpy_s() is the "secure" version of strncpy(), and all it does (differently from strncpy()) is require you to specify the length of the destination buffer.Plutonic
@Plutonic I was indeed looking for "why strncpy() is insecure as compared to strncpy_s()?"Drysalter
read these: strlcpy and strncpy. Very nicely written.Hellenhellene
I heard about that strcpy is not secure in Windows version, but Linux version is better.Prominent
@Marc W: That is a completely incorrect understanding. strncpy is not a safe version of strncpy. strncpy is completely unrelated to strcpy.Grefer
My rant on the topic of strncpy(): the-flat-trantor-society.blogspot.com/2012/03/…Satem
Just found this interesting article: lwn.net/Articles/507319 about strlcpy not being accepted to glibc and points out that string size checking should be done per case.Softboiled
P
50

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.

Plutonic answered 15/5, 2009 at 17:20 Comment(15)
good point. So, even with strncpy, make sure the buffer ends with a '\0'.Alderney
+1, but it's good to note that strncpy only insecure when you forget to manually add the null terminator. If you have trouble remembering to,consider a wrapper function, which always sets the final character to '\0' after calling strncpy.Antrim
@ojrac, I think that the wrapper is named strncpy_s(), at least for users of Microsoft's C runtime. There's also _wcsncpy_s() for the wide-char enthusiasts.Saucer
@RBerteig, note that MS strncpy_s and company are not 1:1 strncpy replacements as they do not zero-fill the buffer. They are a better strcpy although IMHO strl* functions are more versatile and faster. @ojrac, it is still too prone to misuse, for one thing you have to remember both that and to copy (bufsize-1) instead of (bufsize) or have your "rm -Rf /a" turned into "rm -Rf /".Ideology
@jbcreix: strncpy is not guaranteed to fill the buffer with zeros either.Lifework
"NULL termination" isn't correct. ASCII character \0 is usually written "NUL" to avoid confusion with the NULL pointer.Phosphoresce
@Billy ONeal, opengroup.org/onlinepubs/007908775/xsh/strncpy.html , opengroup.org/onlinepubs/009695399/functions/strncpy.html and the C1x draft disagree with you. Unless ANSI C says otherwise, not zero-filling is nonstandard behavior. Then again, Microsoft doesn't support C at all; all they have is a C++ compiler.Ideology
That link is dead. Is it available somewhere else?Bareback
That particular exploit method isn't critical to this answer; you can find several equivalent vulnerabilities through Google. See, for example, Exploring Adjacent Memory Against strncpy.Plutonic
@Sionide21: I haved edited the answer but it's under reviews. Following is the link: blogs.msdn.com/b/oldnewthing/archive/2005/01/07/348437.aspxIgnore
Same problem that in the other answers. strncpy is a conversion function, not a safe-string copying function. It converts zero-terminated strings to fixed-with strings. Fixed-with strings are not generally zero-terminated, which is why the result of strncpy is not supposed to be zero-terminated in general. Just because incompetent code writers often abuse strncpy for "safe string copying" in a basis for the claims of some "insecurity" inherent in strncpy.Grefer
@Chris Lutz: The difference between NUL and NULL has nothing to do with potential confusion between the two. The ASCII null character predates the C macro NULL. In ASCII, control characters are conventionally abbreviated to two or three uppercase characters, so the abbreviation for the null character is NUL. And, in fact, the official Unicode name for U+0000 is "NULL" which coincidentally matches the common C macro.Stereoscopy
Link is dead. Update?Abloom
So, what is the solution? I don't know any other function, and the function that some people mention (strlcpy) is from BSD,Warmedover
Currently, according to the comments I am using size_t len = strlen(mystring); strncpy(destination, mystring, len +1); destination[len] = '\0';Warmedover
E
12

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.

Ea answered 1/6, 2012 at 7:12 Comment(1)
strncpy is not better than strcpy. strlcpy is useful where it is available and easy to rewrite where it is not.Carilla
A
7

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.

Annoy answered 22/10, 2010 at 17:29 Comment(0)
G
5

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.

Grefer answered 10/9, 2014 at 14:50 Comment(1)
When people say "strncpy is insecure" what they mean is "It doesn't have a pit of success." Which is true.Irma
R
2

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.

Roslynrosmarin answered 19/8, 2018 at 17:5 Comment(2)
What does this answer add to the previous ones?Carilla
@Carilla Just an illustration than 9 years after the OP, those functions are still so dangerous (and the patch illustrates why) that they are banned from C codebase (like, here, the one from Git)Roslynrosmarin

© 2022 - 2024 — McMap. All rights reserved.