< Day Day Up > |
The prevention of buffer overflows rests with the initial programmers. You should use languages that don't have these vulnerabilities, such as Java, Python, or Perl. However, many thousands of programs and even operating systems are written in C, and many have C and C++ functions that do not provide boundary checking as they work with data. This subsequently allows more data to be copied from one variable to another. For example, strcpy() allows more data to be copied to the destination than the destination can actually support, so the data starts to overflow, as described earlier in the chapter. Therefore, one of the most basic steps is simply not to use strcpy() in your code. Instead, you should use a function such as strncpy(), which does limit the amount of data being copied. Table 14-2 lists some of the functions with similar vulnerabilities that you should avoid, with possible alternatives.
Most of these standard functions come with a corresponding counterpart that controls the length of data with which it can work. Tip You can use source code tools such as Cigital Security's ITS4 at http://www.cigital.com/its4/ as a smart grep-type program that can assist in finding vulnerable functions. Library Tools to Prevent Buffer OverflowsTools such as libsafe actually help to track stack pointers and assist in prevention of stack smashing. The libsafe tool from Bell Labs replaces dangerous functions with safer versions in the libc library. This helps to track stack return pointers and prevents them from being overwritten. If they are overwritten, libsafe terminates the program. libsafe definitely helps with unknown stack problems in applications, but it might degrade your performance slightly when you run the application. For more information, see http://www.research.avayalabs.com/project/libsafe/doc/usenix00/paper.html. Compiler-Based Solutions to Prevent Buffer OverflowsYou can now recognize some of the bad functions, but some programs still use them. Compiler-based solutions can be of assistance when you use them with the original source code. During compile, they slightly modify the program by adding code. They can use a few different approaches. One style applies boundary checking code to every return pointer. However, it might make the executable 100% bigger than the original. A program called StackGuard (http://immunix.org/) takes another approach. StackGuard works by inserting an extra word next to the return address called a canary. This canary word is cross-checked when the function returns. If the canary value has changed, a stack smash has occurred. If this occurs, StackGuard logs the event to a syslog server and terminates the program. Using a Non-Executable Stack to Prevent Buffer OverflowsLocking the stack from execution is another approach that you can use to prevent buffer overflows. For example, Solar Designer has created a patch for Linux that has the capability to prevent code execution from within the stack, which greatly assists in the prevention of stack smashing. Some legitimate programs might no longer work, however, because they actually try to execute commands from within the stack. For more information, see http://www.openwall.com/linux/. Note You can find an interesting paper titled "Defeating Solar Designer's Non-Executable Stack Patch" at http://www.insecure.org/sploits/non-executable.stack.problems.html. In addition, you can learn about getting around non-executable stacks (and fix) at http://www.securityfocus.com/archive/1/7480. Preventing buffer overflows can be quite tricky if you don't have control over the source code. Even if you do have control over it, you might not be able to rewrite the entire application or even make it completely free of overflow issues. All you can do is educate programmers, write more secure programs, and apply the patches to existing applications as they become available. |
< Day Day Up > |