We've already discussed buffer overflows at the presentation layer above; of course, there's ample opportunity to smash your stack even if you're using middleware frameworks such as CORBA that do all the presentation layer stuff for you.
At the application layer, buffer overflows often occur when the programmer expects the length of certain variable length items not to exceed a ``sane'' limit. Classic examples include assumptions based on the constraints of the ``standard'' Unix file systems. The application receives the path name of a file from the network? Sure, we all know that path names in Unix can't exceed 1024 bytes, so it's okay to copy that string to a 1024 byte buffer.
There are several ways in which you can protect yourself from this type of problem. One, which is really what I recommend, is to always make sure that whenever you copy a string received from the network to another buffer, you explicitly limit the amount of data copied, using functions such as strncpy and snprintf.
A different solution is to have a string handling library do all the string operations, and review the library for buffer overflows. Even better, use a library that's already been audited by someone else. One such library is Dan Bernstein's XXX library (FIXME) which is really good. Unfortunately it's not included in many commercial products due to somewhat peculiar licensing term. XXX: need another one; didn't Chris Evans write one?
Yet another approach is to make sure that all buffers are large enough to hold whatever string you receive from the client. Note that an attacker can of course send arbitrarily long strings, but if your application does not accept network packets longer than say 2048 bytes, then you know no client supplied string argument can be longer than that.
Can we therefore assume that we're on the safe side if we make all string buffers twice that large? The answer is most likely, yes, which may give us a warm fuzzy feeling but is not really satisfying from a security perspective. So in order to be really sure, we would need to check the entire source code if there's any place where two or even three client supplied strings are concatenated and stored in a string buffer. This is a hairy job, because it usually requires a deep understanding of the code, and unfortunately, the principal author and the guy charged with fixing the security problems are often not the same.
Note that the third approach is also quite bad from a maintenance perspective because basically each new release requires a full source code review. We'll come back to these issues in chapter 10.