A generic buffer overflow takes place when a buffer that has been assigned a specific storage space contains more data than it can handle. Programs and applications are vulnerable because boundary checks are not completely done or they are skipped completely in most cases. Programming languages such as C are vulnerable. As some functions, such as strcat(), strcpy(), sprint(), vsprintf(), bcopy(), gets(), and scanf(), in C language do not check for buffer size, they can be exploited.
In this chapter, we will learn about buffer overflows, types of buffer overflows, and buffer overflow steps. We will also learn about smashing the stack, mutating a buffer overflow exploit, and identifying buffer overflow detection tools and buffer overflow countermeasures tools.

17.1 Understand buffer overflows (BoF)

Exam Focus: Understand buffer overflows (BoF). Objective includes:

·  Understand buffer overflows (BoF) and examples of buffer overflows.

·  Understand stack-based buffer overflow.

·  Know heap-based buffer overflow.

·  Understand stack operations.

·  Identify buffer overflow steps.

·  Analyze attacking a real program.

Buffer overflow

Buffer overflow is a condition in which an application receives more data than it is configured to accept. It helps attackers not only to execute a malicious code on the target system, but also to install backdoors on the target system for further attacks. Buffer overflow attacks are almost always due to sloppy programming or poor memory management by the application developers.
A generic buffer overflow takes place when a buffer that has been assigned a specific storage space contains more data than it can handle. Programs and applications are vulnerable because boundary checks are not completely done or they are skipped completely in most cases. Programming languages such as C are particularly vulnerable, since functions, such as strcat(), strcpy(), sprint(), vsprintf(), bcopy(), gets(), and scanf(),do not check for buffer size, and can therefore be exploited.

Types of buffer overflow

The primary types of buffer overflow are:

·  Stack-based buffer overflow

·  Format string overflow

·  Heap-based buffer overflow

·  Integer overflow

Stack-based buffer overflow

A stack is the Last in First Out (LIFO) abstract data type and data structure. It can have any abstract data type as an element. It is like a buffer that holds all the information that is needed by the function.
A stack-based buffer overflow attack uses a memory object known as a stack. The hacker develops the code which reserves a specific amount of space for the stack. If the input of the user is longer than the amount of space reserved for it within the stack, the stack will overflow. An attacker injects malicious code on the stack and overflows the stack to overwrite the return pointer to switch the flow of control to the malicious code.

Stack buffer overflow attacks

Buffer overflows, also known as 'smash the stack' are a favorite exploit for hackers. Both commercial and in-house applications are susceptible to buffer overflow attacks. Here are common ways for a stack buffer overflow attack to occur:

·  Overwriting a local variable that is near the buffer in memory on the stack to change the behavior of the program which may benefit the attacker.

·  Overwriting the return address in a stack frame. Once the function returns, execution will resume at the return address as specified by the attacker, usually a user input filled buffer.

·  Overwriting a function pointer, or exception handler, which is subsequently executed.

It is very important for developers, and QA professionals to understand how buffer overflows work so they can plan for vulnerability testing on home-grown applications prior to deployment.

Format string overflow

A format string overflow attack is caused by the use of unfiltered user input. It can be used to crash a program or to execute harmful code. It modifies the flow of an application by using string formatting library features to access other memory space. Vulnerabilities occur due to the direct use of user-supplied data as formatting string input for certain C/C++ functions. A format string attack is related to the buffer overflow and integer overflow attacks.

Heap-based buffer overflow attack

Heap is an area of memory used by an application. Memory on the heap is dynamically allocated by the application at run-time and typically contains program data. Exploitation is performed by corrupting this data in specific ways to cause the application to overwrite internal structures such as linked list pointers.
In a heap-based buffer overflow attack, an attacker overflows a buffer that is placed on the lower part of heap, overwriting other dynamic variables, which can have unexpected and unwanted effects.
If an application copies data without first checking whether it fits into the target destination, the attacker could supply the application with a piece of data that is large, overwriting heap management information. In most environments, this may allow the attacker to control over the execution of the program.

Integer overflow

Integer overflow, or integer wrapping, is a potential problem in a program. It works upon the fact that the value that can be held in a numeric datatype is limited by the data type's size in bytes. When a value is placed into a data type that is too small to hold it, the high-order bits are dropped, and only the low-order bits are stored.

How hackers exploit buffer overflow

In a nutshell, here's how hackers exploit buffer overflows

1.  Determine the presence and location of buffer overflow vulnerability.

2.  Write more data into the buffer than it can handle and overwrite the return address of a function.

3.  Change the execution flow to the hacker code.


Example:
An attacker assumes that a string function is exploited and sends a long string as the input. This string causes a segmentation error by overflowing the buffer. The return pointer of the function is overwritten, and the attacker becomes successful in changing the flow of the execution. A user should know the exact address and size of the stack and make the return pointer point to his code for execution if he has to insert code in the input.

Other ways to exploit code

·  Shellcode:is a small piece of code that is used as payload when software vulnerability is exploited. As buffers overflow easily if the conditions match, they are considered as soft targets for attackers. Buffer overflow shellcodes are written in assembly language. They exploit vulnerabilities in stack and heap memory management.

·  No operation (NOP) sleds: There are many CPUs that have a No Operation (NOP) instruction. Essentially, they are set of instructions that effectively do nothing at all. A NOP-sled is the oldest and most widely known technique for successfully exploiting a stack buffer overflow. It solves the problem of finding the exact address of the buffer by effectively increasing the size of the target area. To do this, much larger sections of the stack are corrupted with the HYPERLINK "http://en.wikipedia.org/wiki/No-op" \o "No-op" no-op machine instruction.
Because of the popularity of this technique, many vendors of HYPERLINK "http://en.wikipedia.org/wiki/Intrusion_prevention_system" \o "Intrusion prevention system" intrusion prevention systems will search for this pattern of no-op machine instructions in an attempt to detect shellcode in use. In addition, because exploits using this technique still must rely on some amount of luck that they will guess offsets on the stack that are within the NOP-sled region, they have a higher risk of being detected. An incorrect guess will usually result in the target program crashing and alert the application or system administration team to a possible NOP attack.

·  Canaries: Canaries or canary words are known values that are placed between a buffer and control data on the stack to monitor buffer overflows. When the buffer overflows, the first data to be corrupted will be the canary, and a failed verification of the canary data is therefore an alert of an overflow, which can then be handled, for example, by invalidating the corrupted data.

17.2 Reasons for buffer overflow attacks, and skills required to program buffer overflow exploits

Exam Focus: Reasons for buffer overflow attacks, and skills required to program buffer overflow exploits. Objective includes:

·  Examine smashing the stack.

·  Understand how to mutate a buffer overflow exploit.

·  Learn how to identify buffer overflows.

Smash the stack

Recall that a 'smash the stack' is a buffer overflow situation. On many C implementations, it is possible to corrupt the execution stack by writing past the end of an array declared auto in a routine. Code that does this is said to smash the stack, and can cause return from the routine to jump to a random address. The function will then jump to whatever address is on the stack when the function has been performed. Buffer overflow permits a user to change the return address of a function. This almost always results in corruption of adjacent data on the stack, and in cases where the overflow was triggered by mistake, will often cause the program to crash or operate incorrectly.
If the affected program is running with special privileges, or accepts data from untrusted network hosts such as a "http://en.wikipedia.org/wiki/Webserver" \o "Webserver" webserver, then the bug is a potential security vulnerability. If the stack buffer is filled with data supplied from an untrusted user then that user can corrupt the stack in such a way as to inject executable code into the running program and take control of the process. Once the stack is smashed, an attacker can create a backdoor using tools like inetd, Trivial FTP (TFTP), or Netcat in order to make raw and interactive connections. This is one of the oldest and more reliable methods for "http://en.wikipedia.org/wiki/Hacker_(computer_security)" \l "Classifications" \o "Hacker (computer security)" black hat hackers to gain unauthorized access to a computer.

Reasons for buffer overflow attacks

Buffer overflow attacks depend on the lack of boundary testing and a machine that can execute a code that resides in the data/stack segment. The lack of boundary is common and the program usually ends with the segmentation fault or bus error. The offender must create the data to be fed to the application to exploit buffer overflow for gaining access to or escalate privileges. Random data will produce a segmentation fault or bus error, never a remote shell or the execution of a command.

C library functions that cause buffer overflow attacks

C programs are critically vulnerable to buffer overflow attacks. C library functions, such as gets(), strcpy(), strcat(), sprintf(), vsprintf(), etc. are responsible for buffer overflow in most cases. The scanf() function can also be the reason of a buffer overflow attack.

Identifying buffer overflows

Take the following steps to identify buffer overflows:

1.  Run a web server on the local machine and issue requests with long tags-all long tags end with "$$$$$".

2.  Search core dump for "$$$$$" in order to determine the overflow location if the web server crashes.

3.  Use automated tools, such as codeBlocker, eEye Retina, etc., and disassemblers and debuggers.

4.  Construct an exploit by using IDA-Pro.

Detect buffer overflows in a program

There are at least two ways to detect buffer overflows:

1.  Source code: In this case, the hacker can verify the presence of boundary checks after looking for strings declared as local variables in functions or methods. Improper use of standard functions should be checked, especially those related to strings and input/output.

2.  Feed the application with huge amounts of data and check for the abnormal behavior.

SmashGuard

SmashGuard is a hardware-based solution for stack-smashing buffer overflow. At each function call, SmashGuard keeps a copy of the function Return Address written to the program stack in a LIFO buffer on the CPU. Just before the function is completed, the Return Address of the function is compared with the address at the top of the stack. If both addresses match, the program flow continues without any interruption. However, if both addresses do not match each other, an error is displayed.

Skills required to program buffer overflow exploits

The following skills are required to program buffer overflow attacks:

·  Understanding of stack and heap memory processes

·  Understanding of the working of system calls at the machine code level

·  Understanding of assembly and machine language

·  Understanding of C and Perl programming language

·  Understanding of compiling and debugging tools such as gdb

Testing for format string conditions

Format string vulnerabilities manifest in the Web server, application servers, Web application using C/C++ based code, and CGI scripts written in C. Input parameters are manipulated by an attacker to include %x or %n. The attacker checks instances of code (assembly fragments) to identify the presence of a format string vulnerability. The address of a format type specifier being pushed on the stack is clearly visible before a call to print is made when the disassembly is examined using IDA Pro.

17.3 Testing for heap overflow conditions: heap.exe, and understand OllyDbg debugger

Exam Focus: Testing for heap overflow conditions: heap.exe, and understand OllyDbg debugger. Objective includes:

·  Test for heap overflow conditions: heap.exe.

·  Understand steps for testing stack overflow in OllyDbg debugger.

·  Identify buffer overflow detection tools.

·  Understand defense against buffer overflows.

Testing for heap overflow conditions

The variants of the heap overflow (heap corruption) vulnerability including those that permit overwriting function pointers and exploit memory management structures for arbitrary code execution are identified. Longer input strings than expected are supplied to test for heap overflows. When debugging a windows program, a heap overflow can appear in several different forms. The most common one being a pointer exchange taking place after the heap management routine comes into action.

Testing a stack overflow in OllyDbg debugger

To test a stack overflow in OllyDbg debugger:

1.  Attach a debugger to the target application or process, and generate malformed input for the application.

2.  Subject the application to malformed input, and inspect responses in a debugger.

For example, an attacker can take the following steps to overwrite the instruction pointer and control program execution: