Well, it's as simple as this: if it hurts, don't do it. In other words, now that you know how dangerous buffer overflows are, make sure to avoid them!
Easier said than done, arguably. However, I hope I have scared you enough by now, and you'll be aware of this pitfall when starting your next project.
Here's a brief list of useful hints that can help you avoid introducing buffer overflows in your code:
Note that strncpy does not copy the terminating NUL byte if the destination buffer is too small. The proper way of using it goes like this:
char buffer[BUFSZ];
strncpy(buffer, somestring, sizeof(buffer)-1);
buffer[sizeof(buffer)-1] = '\0';
char buffer[BUFSZ], *sp, *end;
sp = buffer;
end = buffer + sizeof(buffer);
while (complicated condition) {
more complicated stuff
/* Now try to append string to buffer. Note that
* the >= comparison takes care of the NUL byte at the
* end of the appended string: */
if (sp + strlen(string) >= end)
return -1; /* too bad, not enough room */
strcpy(sp, string);
sp += strlen(string);
}
Admittedly, this is something every book on software design tells you on page three. But in a security context, it nevertheless bears repeating because if you have the code once, you will be able to go over it with a fine tooth comb, looking for problems such as buffer overflows. If you have the same code scattered all over your project, in several copies, the motivation to do so (and the concentration with which you perform this) may be less, resulting in less secure code.
Even if you're very careful with your code, have someone else review your code for security problems, if possible. As I said previously, we programmers tend to develop a blind spot when it comes to security flaws in our own design. Having someone else take a look at it from a different angle, and with the intent on exposing its security flaws, will help a lot. This sort of review is commonly called a (source code) audit.
Auditing code for buffer overflows is a boring and tedious task. Some quick results can be achieved by grepping the source code for calls of strcpy, sprintf, etc. But if you don't find any of these traditional troublemakers this doesn't mean the code is perfectly safe. It may just as well contain code that copies a string character by character from one buffer to another, without proper bounds checking.
Chapter 10 has more information about auditing for security problems.
In my opinion, keeping security in mind during the design of a software project, and auditing the code once in a while, is the sine qua non condition of secure coding. However, sometimes it can be useful to have additional protection. The next two sections will discuss two mechanisms that offe additional protection.