Buffer Overflow Basics with Example

Introduction

Buffer overflows have been the most common form of a security vulnerability in the last ten years. Buffer overflow attacks form a substantial portion of all security attacks simply because buffer overflows vulnerabilities are so common and so easy to exploit. Most of the exploits based on buffer overflow aim at forcing the execution of malicious code, mainly in order to provide a root shell to the user. A buffer overflow occurs when more data are written to a buffer than it can hold.

Buffer overflows happen when there is improper validation. Like it or not, all buffer overflows are a product of poorly constructed software programs. These programs may have multiple deficiencies such as stack overflows, heap corruption etc referred to as simply buffer overflows. Programs written in C are particularly susceptible to buffer overflow attacks. Pace and performance were more important design considerations for C than safety. Hence, C allows direct pointer manipulations without any bounds checking. The standard C library includes many functions that are unsafe if they are not used carefully.

Buffer Overflow

To understand buffer overflow attacks, we must first understand what a buffer overflow is. A buffer is an area of memory allocated with a fixed size. It is commonly used as a temporary holding zone when data is transferred between two devices. When user input exceeds the maximum size of the buffer, overwriting the other areas of the memory and corrupting those areas results in a buffer overflow.A common example might be an application which asks for a username it expects to be no longer than, 8 characters.boolean

 rootPriv = false;char name[8];cin >> name; 

If the user enters a username of more than 8 characters there is a potential problem if the application tries to store the username in a string buffer of 8 bytes, which can take a maximum of 8 letters. 

Types of Buffer Overflow
  • Stack Overflow

Stack overflows have been considered the most common type of error that can be remotely exploitable. These are caused by a lack of separation in data and structures that control the data. Of the different types of buffer overflows, stack overflows have been considered the easiest to exploit.

  • Heap Overflow

A heap is a memory area that has been allocated dynamically. Heaps are dynamically created (e.g., new, malloc) and removed (e.g., delete, free). Heaps are necessary as the memory-size needed by the program is not known former or it may require large memory than stack.Heap overflow is as same as stack overflow. When a program copies data without checking whether it can store or not in the given destination, then the attacker can easily overwrite data and instruction in heap.

  • Off-by-One Errors

An off-by-one error is a specific type of buffer overflow that occurs when a value is one iteration off what it is expected to be. This can often be due to miscounting the number of times a program should call a specific loop of code. The error may result in rewriting of one digit in the return pointer in the stack, which allows a hacker to direct the pointer to an address containing malicious code.

  • Format String Overflow

A format string attack occurs when a program reads input from the user, or other software, and processes the input as a string of one or more commands. If the command that is received differs from that which is expected, such as being longer or shorter than the allocated data space, the program may crash, quit or make up for the missing information by reading extra data from the stack; allowing the execution of malicious code

Types of Buffer Overflow Attacks

A buffer overflow attack may be two types. One is remote and another is local. In case of remote attack, the attacker uses network port, channel to achieve unauthorized access and tries to get administrator privileges. It is very common today as the use of Internet spread widely in practice. On the other hand, in a local attack, attacker gain direct access of the target system, and then enhances his access privilege.

Consequences of Buffer-Overflow
  • Availability: Buffer overflows generally lead to crashes. Other attacks leading to lack of availability are possible, including putting the program into an infinite loop.
  • Access control: Buffer overflows often can be used to execute arbitrary code, which is usually outside the scope of a program’s implicit security policy.
  • Other: When the consequence is arbitrary code execution, this can often be used to subvert any other security service.
How to Exploit the Buffer-Overflow Vulnerability

To fully exploit stack buffer-overflow vulnerability, we need to solve following challenging problems.

  • Writing malicious code: the most powerful malicious code is to invoke the shell, so we can run any command we want in that shell.
  • Jumping to the malicious code: To jump to the malicious code that we have injected into the target program’s stack, we need to know the absolute address of the code so that when the function returns, it will return to our malicious code.
  • Injecting the malicious code: With the buffer overflow vulnerability in the program, we can easily inject malicious code into the memory of the running program.

Shellcode: Shellcode is the code executed when vulnerability has been exploited. It is called shellcode because it typically starts a command shell from which the attacker can control the compromised machine. Shellcode are very common in exploitation of vulnerabilities such as stack and heap-based buffer overflows as well as format strings attacks. Basically shellcode is a machine code used as the payload in the exploitation of a software bug. From the hacker’s point-of-view, having accurate and reliable shellcode is a requirement for performing any real-world exploitation of vulnerability. If the shellcode isn’t reliable, the remote application or host could potentially crash.

Examples: C program vulnerable to Buffer Overflow

Below is the C program having Buffer Overflow Vulnerability.

#include<stdio.h>
void main()
{
 char *fname;
 char *lname;
 fname=(char *)malloc(10);
 lname=(char *)malloc(10);
 printf("address of first name:%d\n", fname);
 printf("address of last name:%d\n", lname);
 printf("Difference between address is :%d\n", lname-fname);
 printf("Enter pet name:");
 gets(fname);
 printf("hello %s\n",fname);
 system(lname);
}

The malloc function is used to allocate a certain amount of memory during the execution of a program. The malloc function will request a block of memory from the heap. If the request is granted, the operating system will reserve the requested amount of memory. When a system function has executed the content in the last name will be executed. In the above program, we allocate 10 bytes to the first name which is dynamically allocated memory and another 6 additional bytes for malloc call. We can compile the above program (new.c) as 

Compile C program
Compile C program

We execute the program and get to know that the address between first name and last name is 16 bytes. Then we enter the pet name and the program results hello pet name i.e John martin. When the user gives the input of less than the 16 digits then the program will execute normally as the function doesn’t go up to last name variable. 

Execute C program
Execute C program

We again execute the program with different pet name i.e jonathhan lewinters it results in hello jonathhan lewinters and ers command not found. This means the command we are trying to execute is not found in the shell. In this execution starting 10 bytes are assigned with the first name, 6 bytes are assigned with malloc function and remaining 3 goes to last name i.e ers. 

Execute C program
Execute C program

Again we execute our program with same pet name i.e jonathhan lewinters but in place of ers we use cat /etc/passwd.

Execute C program
Execute C program

This results the buffer overflow. This buffer overflow is caused because the gets() function doesn’t limits the length of input. In this way an attacker can exploit the application having buffer overflow vulnerability to execute the system command. To overcome from this kind of problem we can use the fgets(fname,10,stdin) function.

Buffer overflow attack in tugzip 3.5 using backtrack

TUGZip 3.5 is prone to a remote buffer-overflow vulnerability because it fails to perform adequate boundary checks on user-supplied data. The vulnerability occurs when handling specially crafted ZIP files. By this vulnerability, an attacker can exploit this issue to execute arbitrary code with the privileges of the user running the affected application. Failed exploit attempts will result in a denial-of-service condition.
Download TugZip 3.5 and install that software on a windows machine. Open Backtrack machine and start Metasploit by using msfconsole command in the console. Search for tugzip in msf and use exploit tugzip.If you don’t have this exploit download it from the resource. 

msfconsole buffer overflow
msfconsole

Set payload of reverse TCP and set LHOST. LHOST is localhost IP address means backtrack machine IP address in my case it is 192.168.1.11. 

Set payload of reverse TCP
Set payload of reverse TCP

Run the exploit. It will create .zip file. Send that file using some social-engineering method to victim machine. 

Run the exploit
Run the exploit

So now we need to open a listener so we can listen for the zip connecting back so that we get a session. Create a payload handler on the backtrack machine. 

open a listener
open a listener

Set payload of reverse TCP. Set LHOST and run the exploit. When the victim open that zip file in tugzip you will get meterpreter session opened in backtrack. 

run the exploit

Meterpreter provides an interactive shell which allows you to use extensible features at run time. Beautiful fact about meterpreter is its ability to remain undetectable by most commonly used Intrusion Detection systems. Meterpreter also provides ease of multitasking by giving us the ability to create multiple sessions.

Prevention against buffer overflows errors

Buffer overflow vulnerabilities are the result of poor input validation: they enable an attacker to run his input as code in the victim. Following are the steps used to prevent (or detect) buffer overflow vulnerabilities.

  • 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.
  • Static Techniques: One of the best ways to prevent the exploitation of buffer overflow vulnerabilities is to detect and eliminate them from the source code before the software is put into use. Tools designed to perform automatic source code analysis complement the act of a manual audit by identifying potential security violations including functions that perform unbounded string copying. Some of the best known tools are its4, RATS, and LCLin.
  • Dynamic run-time checks: In this an application has restricted access in order to prevent attacks. This method primarily relies on the safety code being preloaded before an application is executed. This preloaded component can either provide safer versions of the standard unsafe functions, or it can ensure that return addresses are not overwritten. One example of such a tool is libsafe.
  • Compiler Modifications: If the source code is available, individual programs can have buffer overflow detection automatically added in to the program binary through the use of a modified compiler. StackGuard, ProPolice, StackShield, and RAD are such compilers.
  • Stack executes invalidation: Because malicious code (for example, assembly instructions to spawn a root shell) is an input argument to the program, it resides in the stack and not in the code segment. Therefore, the simplest solution is to invalidate the stack to execute any instructions.
Conclusion

A buffer overflow occurs when more data are written to a buffer than it can hold. The excess data is written to the adjacent memory, overwriting the contents of that location and causing unpredictable results in a program. Buffer overflows happen when there is improper validation. It is considered a bug or weakness in the software. Buffer overflows still account for the largest share of software vulnerabilities. Particularly dangerous is the area of remotely exploitable vulnerabilities, where attackers hijack hosts in the Internet to perform criminal activities on behalf of others. The prevention technologies can make exploiting a buffer overflow considerably harder, but no tool can solve completely the problem of buffer overflow. However, writing secure code is still the best possible solution to these attacks.

References

Leave a Reply