Saturday, 10 May 2008

What can programmers can do to avoid buffer overflows

A buffer is a contiguous allocated chunk of memory, such as an array or a pointer in C. In C and C++, there are no automatic bounds checking on the buffer, which means a user can write past a buffer” (Grover, 2003). Manipulation of the buffer which occurs before it is read or executed may lead to the failure of an exploitation attempt (Lilly, 2002).

The primary solution to common buffer overflow problems mainly targets the impediment of significant system attacks. Although there is no panacea for all possible attacks, the methods below can make it more difficult to create or cascade buffer overflows and, hence, devastate the stability of stacks.

Both Viega & Messier (2003) and Grover (2003) note a number of protective actions that may help reduce the effects and likelihood of a buffer overflow occurring:

  1. Write secure code: Buffer overflows are the consequence of entering a greater amount of code into a buffer than it expects. “C library functions such as strcpy (), strcat (), sprintf () and vsprintf () operate on null terminated strings and perform no bounds checking. gets () is another function that reads user input (into a buffer) from stdin until a terminating newline or EOF is found. The scanf () family of functions also may result in buffer overflows”[1]. One of the most effective means to mitigate the risk from a buffer overflow is to block them and not make them feasible.

  2. Stack execute invalidation: Malicious code is an input argument to the program, it resides in the stack and not in the code segment. This is mitigated by not allow the stack to execute any instructions. Any code that attempts to execute any other code residing in the stack will cause a segmentation violation. This is not a simple solution.

  3. Compiler tools: Modern compilers and Linkers alter the method in which a programme is compiled. This may allow bounds checking to go into compiled code automatically, without changing the source code (Viega & Messier, 2003). These compilers generate the code with built-in safeguards that try to prevent the use of illegal addresses. Any code that tries to access an illegal address is not allowed to execute. (One tool is StackGuard. This detects and prevents “smash stacking attacks” by shielding the return address on the stack, stopping it from being altered. It places a canary word next to the return address whenever a function is called. If the canary word has been altered when the function returns, then some attempt has been made on the overflow buffers. It responds by emitting an alert and halting).

  4. Dynamic run-time checks: The application is only allowed restricted access which aides in the prevention of attacks. This technique chiefly relies on the “safety code” being preloaded before an application is executed (Grover, 2003). This preloaded component may either present a protected version of the standard insecure functions. It may also ensure that return addresses in the system are not allowed to be overwritten (Viega & Messier, 2003).
[1] Grover, 2003

No comments: