Overflows

This page is about one of the most common security flaws, overflows. An overflow is the condition when the input is expected to be less than e.g. 10, but isn't. Most commonly, we find security flaws related to buffer overflows in C/C++ programs working with arrays (*very* commonly is problems derived from strcat, scanf, gets and similar calls). There are none-vulnerable function calls like strncat which protects against this problem, which you should always use.

Buffer Overflow

Common vulnerable code consits of data being moved (like using strcat) or read (like using gets) into a local array. Unfortunatly, the local array as well as the function return address will both be stored on the stack.

This extremly dangerous because the attacker will easily be able to feed you hostile code instead of data, and with a simple trick the attacker will make your program execute the code. This vulnerability is know as "buffer overflow", and is a special case of the overflow problems.

Consider the following, vulnerable, code.

  void f() {
    char s[512];
    gets(s)
  }

Then your software calls f(), it will make room for s[] on the stack. Picture youself with the stack looking like this:

           stack:
  ==========================
  |                        |
  |          s[]           |
  |                        |
  ==========================
  |                        |
  |     return address     |
  |                        |
  ==========================
  |                        |
  :                        :
  .                        .

What the attacker will do is to overwrite s[] with the malicious code of his choice... most likely it will do something you really don't want your program to do! Exploits available on various internet sites contain malicious code which aid the attacker in breaking into a system, or in some cases damage it (as an example, one exploit intentionally breaks /bin/bash which is used by several unix clones)

Then the attacker will write to s[x], only now x will be equal or greater than the size of s[]. This is the "overflow", the attacker writes beyond the end of s[]. As a matter of fact, he will overwrite the return address. The attacker will most likely overwrite it with address to the begining of s[], so that once the function terminates, the malicious code will be executed.

A graph of the modified stack will look like this:

       modified stack:
  ==========================
  |                        |
  |  Malicious code (s[])  | <--+
  |                        |    |
  ==========================    | f() will return to malicious code in s[]
  |                        |    |
  |    address of s[0]     | ---+
  |                        |
  ==========================
  |                        |
  :                        :
  .                        .

It's worth to notice that the biggest problem is the ability for an attacker to modify the return address. This is what makes it possible to make the code behave unexpectedly. In an important program like the unix command su, simply being able to make the program jump into another part of itself could be enough compromise the system.

Counter meassures

Now, numerous things can be done to prevent these vulnernabilities. To begin with, almost every book about C describes how to use more secure function calls, but programmers are lazy, and even good programmers make fatal misstakes once in a while. C programmers should practice safe coding, but automatic protection should be applied as well. Sadly, numerous known defences aren't used, so this problem which has been known for decades is still a problem.

Futher reading

This page is merely intended as an introduction to the problem. In order to develop secure systems, a programmer should at least have some awareness of the methods used by the attackers. Here's some of the "turorials" on the problem which are easily available to any attacker, just as easily as we got our hands of it. If you don't studdy the problem, you are likely repeat others misstakes.