Buffer overflow vulnerabilities are the result of poor input validation: they enable an attacker to run his input as code in the victim. Even when care has been taken to validate all inputs, bugs might slip through and make the application insecure. This article presents the various options available to protect against buffer overflows
Buffer overflow vulnerabilities are the result of poor input validation: they enable an attacker to run his input as code in the victim. Even when care has been taken to validate all inputs, bugs might slip through and make the application insecure. This article presents the various options available to protect against buffer overflows. These methods either check for insecure function calls statically, look for overflow during runtime dynamically or prevent execution of code on the stack.
- Non-executable stack: In this method the stack is configured not to hold any executable code. Kernel patches are available for both Linux and Solaris for configuring a non-executable stack. Data execution prevention in Windows XP and 2003 also protect the stack against buffer overflow. This method protects against stack-based buffer overflow attacks. Heap-based overflows and static data segment overflows cannot, however, be prevented by this technique.
- Static Analysis: In static analysis the source code is parsed for dangerous library calls and race conditions to detect potential buffer overflows. Functions like strcpy and sprintf are vulnerable to buffer overflows, so source code scanners are used to look for incorrect use of these functions. RATS and SPLINT are two such tools; however static analysis is riddled with false positives.
- Dynamic runtime protection: Buffer overflow conditions are detected during the actual running of the program in this method, and an attack thwarted. Different techniques of dynamic runtime analysis are:
- Canary: When a function call is made, a "canary" is added to the return address; if a buffer overflow occurs, the canary will be corrupted. So, before returning to the parent function, the "canary" is checked again to see if it has been modified. Stack Guard uses this technique by implementing it as a patch to the GCC complier; this causes minimum performance delays. Free BSD also has a patch available to do this.
- Copying Return Address: In this method, the return address is saved separately; so even when a buffer overflow exploit overwrites the return address on the stack, it is set back to the original value when the function returns. Stack Shield - a development tool that uses this technique - works as an assembler file processor and is supported by GCC/G++ front ends. Stack Shield however, protects against only overwriting of the return address.
- Array bounds Checking: When an array is read from or written to, this technique double-checks whether the boundaries are being violated. Compaq C Complier and Jones & Kelly‘s GCC patch perform array bounds checking, but at the cost of considerable performance degradation.
- Memory Access checking: Here, verification code is added to the binary when the program is compiled. It checks access violations in real time. Tools like Purify offer this protection with little impact on performance.
- Use safer versions of functions: Safer alternatives are available for all the traditional functions beset by buffer overflows. For instance, strncpy and snprintf are safer than the older strcpy and sprint. When new applications are being developed, ensure that only the safer variants are used.