Introduction
Buffer overflows have been the
most common form of 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
overflows 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.
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
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.
- Stack Overflow
Stack overflows have been
considered the most common type of error that can be remotely
exploitable. Stack overflows 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
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.
- 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.
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
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 is
executed the content
in the last name will be executed.
In above program we
allocate 10 byte to first name which is dynamic allocated memory and
another 6 additional byte for malloc call.
We can compile the above program (new.c) as
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
goes up to last name variable.
We
again execute the program with different pet name i.e jonathhan
lewinters it results 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 first name, 6 bytes are assigned
with malloc function and remaining 3 goes to last name i.e ers.
Again we execute our program with same pet name i.e jonathhan lewinters but in place of ers we use cat /etc/passwd.
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.
TUGZip 3.5 is prone to
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 windows machine. Open Backtrack machine and
start metasploit by using msfconsole command in console.
Search for tugzip in msf and use exploit tugzip.If you don’t have this exploit download it from the resource.
Set
payload of reverse TCP and set LHOST. LHOST is local host IP address
means backtrack machine IP address in my case it is 192.168.1.11.
Run the exploit. It will create .zip file. Send that file using some social-engineering method to victim machine.
So
now we need to open a listener so we can listen for the zip connecting
back so that we get a session. Create payload handler on backtrack
machine.
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.
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.
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 remote
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
- http://destroy.net/machines/security/P49-14-Aleph-One
- https://en.wikipedia.org/wiki/Buffer_overflow
- packetstorm.foofus.com/papers/general/ModernOverflowTargets.pdf
No comments:
Post a Comment