Buffer overflows are a leading type of security vulnerability. This paper explains what a buffer overflow is, how it can be exploited, and what countermeasures can be taken to prevent the use of buffer overflow vulnerabilities.

Introduction

Buffer overflow vulnerabilities are one of the most common vulnerabilities. These kinds of vulnerabilities are perfect for remote access attacks because they give the attacker a great opportunity to launch and execute their attack code on the target computer. Broadly speaking, a buffer overflow attack occurs when the attacker intentionally enters more data than a program was written to handle. The data runs over and overflows the section of memory that was set aside to accept it. The extra data overwrites on top on another portion of memory that was meant to hold something else, like part of the program's instructions. This allows an attacker to overwrite data that controls the program and can takeover control of the program to execute the attacker's code instead of the program. Peikari and Chuvakin point out that, "buffer overflows result from an inherent weakness in the C++ programming language." (Peikari and Chuvakin, 2004) The problem is that C++ and other programming languages (those derived from C++), do not automatically perform bounds-checking when passing data. When variables are passed, extra characters could be written past the variable's end. The overflow consequence could result in the program crashing or allowing the attacker to execute their own code on the target system.

Buffers

In order to make sense of how a buffer is overflowed, one must understand what a buffer is. A program contains code that accesses variables stored in various locations in memory. When a program is executed, a specific amount of memory is assigned for each variable. The amount of memory is determined by the type of data the variable is anticipated to hold. The memory set aside is used to store information that the program needs for its execution. According to Peikari and Chuvakin , "The program stores the value of a variable in this memory space, then pulls the value back out of memory when it's needed." (Peikari and Chuvakin, 2004) A buffer is this virtual space.

Buffer Overflow

In exploiting the buffer overflow vulnerability, the main objective is to overwrite some control information in order to change the flow of control in the program. The usual way of taking advantage of this is to modify the control information to give authority to code provided by the attacker to take control. According to Shaneck, "The most widespread type of exploit is called 'Smashing the Stack' and involves overwriting the return address stored on the stack to transfer control to code placed either in the buffer, or past the end of the buffer." (Shaneck, 2003) The stack is a section of memory used for temporary storage of information. In a stack-based buffer overflow attack, the attacker adds more data than expected to the stack, overwriting data. Farrow explains this in an example, "Let's say that a program is executing and reaches the stage where it expects to use a postal code or zip code, which it gets from a Web-based form that customers filled out." (Farrow, 2002) The longest postal code is fewer than twelve characters, but on the web form, the attacker typed in the letter "A" 256 times, followed by some other commands. The data overflows the buffer allotted for the zip code and the attacker's commands fall into the stack. After a function is called, the address of the instruction following the function call is pushed onto the stack to be saved so that the function knows where to return control when it is finished. A buffer overflow allows the attacker to change the return address of a function to a point in memory where they have already inserted executable code. Then control can be transferred to the malicious attack code contained with the buffer, called the payload (Peikari and Chuvakin, 2004). The payload is normally a command to allow remote access or some other command that would get the attacker closer to having control of the system. As Holden explains, "a computer is flooded with more information than it can handle, and some of it may contain instructions that could damage files on the computer or disclose information that is normally protected- or give the hacker root access to the system." (Holden, 2004) Countermeasures

The best defense against any of these attacks is to have perfect programs. In ideal circumstances, every input in every program would do bounds checks to allow only a given number of characters. Therefore, the best way to deal with buffer overflow problems is to not allow them to occur in the first place. Unfortunately, not all programs are perfect and some have bugs that permit the attacks discussed in this paper. As described by Farrow, "because programs are not perfect, programmers have come up with schemes to defend against buffer overflow attacks." (Farrow, 2002) One technique entails enforcing the computer to use the stack and the heap for data only and to never to execute any instructions found there. This approach can work for UNIX systems, but it can't be used on Windows systems. Farrow describes another scheme using a canary to protect against buffer overflows, but only the kind that overwrite the stack. (Farrow, 2002) The stack canary protects the stack by being put in sensitive locations in memory like the return address (that tells the computer where to find the next commands to execute after it completes its current function). As described by Farrow, "before return addresses get used, the program checks to see if the canary is okay." (Farrow, 2002) If the canary has been hit, the program then quits because it knows that something has gone wrong. As a user of the programs, the best countermeasure is to make sure your systems are fully patched in order to protect yourself from exploits targeting vulnerabilities.

Conclusion

Buffer overflow vulnerabilities are one of the most common vulnerabilities and are likely to continue to be a problem for a long time. One main problem is that C++ and other programming languages do not automatically perform bounds-checking when passing data. However, enforcing secure coding practices will be helpful to any future code. As a user, the best thing to do is to take away the ability for the vulnerability to be exploited by knowing what programs are in use and keeping patches up to date.

References

  • Farrow, R. (2002), "Foundations: What Are Buffer Overflows?", Security Fundamentals | WatchGuard Technologies

  • Holden, G. (2004), Guide to Firewalls and Network Security, Thomson Course Technology, pp. 255.

  • Peikari, C. and Chuvakin, A. (2004), Security Warrior, O'Reilly & Associates, Inc. pp. 161-167

  • Shanech, M (2003), "An Overview of Buffer Overflow Vulnerabilities and Internet Worms",

  • Security Focus, (2004),


Erica is currently a student at the University of Louisville majoring in Computer Information Systems.