Buffers are memory storage sections that keep data briefly while being transported between locations. A buffer overflow (or buffer overrun) occurs when the volume of data exceeds the storage capacity of the memory buffer.
As a result, when the application attempts to write data to the buffer, nearby memory addresses are overwritten.
For example, if a buffer for sign-in credentials is designed to accept inputs of 8 bytes for the username and password, and a transaction requires an input of 10 bytes (two bytes more than planned), in that case, the software may write the excess data outside the buffer boundary.
Buffer overflows are a problem that can occur in any sort of software. They generally occur due to incorrect inputs or an insufficient amount of buffer space being allocated.
If the transaction overwrites executable code, the program may perform erratically, producing inaccurate results, memory access issues, or crashes.
A buffer overflow occurs when a software or process tries to write more data to a fixed-length block of memory or buffer, than the buffer is allocated to retain.
This type of overflow can be prevented if the software contains acceptable bounds checking to flag or delete data transferred to a memory buffer in excess.
Buffers are limited in size; any additional data overwrites values in memory addresses adjacent to the destination buffer.
A buffer is regarded as a temporary storage location for data. When a program or system operation places more data (than was originally allocated to be stored), the extra data overflows.
Some of that data leaks out into other buffers, corrupting or overwriting whatever information they were holding. These additional data overflows are considered Buffer Overflow Exploits or Buffer Overflow Vulnerability.
The extra information in a buffer-overflow attack may contain precise instructions for activities intended by a hacker or malicious user; for example, the data could prompt a response that damages files, modifies data, or exposes personal information.
A buffer-overflow vulnerability would be used by the attacker to take advantage of an application waiting for user input.
A buffer overflow might happen accidentally or as a result of malicious activity. A hacker can deliver arbitrary code to the software, which is a carefully constructed input.
The program tries to store the input in a too-small buffer to hold it. If the extra data is written to the next RAM, it will erase any existing data.
The exploited function’s return pointer — the address to which the process should go next — is included in the original contents of the buffer.
On the other hand, the attacker can change the settings to point to any address they want. The new values are usually assigned to a location where the exploit payload is located. The process’s execution path is changed, and control is transferred to the attacker’s malicious code.
Consider an application that is waiting for users to submit their names. Instead of entering the name, the hacker would type an executable command to surpass the stack size. Usually, the command is something simple.
For example, in a Linux context, the command is usually EXEC(“sh”), which instructs the system to open a command prompt window, referred to as a root shell in Linux circles. |
However, an executable command overflowing the buffer does not mean it will be executed.
The attacker or threat actor must specify a return address that points to the malicious command. The stack eventually overflows, causing the program to partially crash.
It then tries to recover by traveling to the return address, but the address has been modified to point to the command supplied by the hacker.
The hacker must be aware of the location of the harmful command.
To avoid providing the exact address, malicious commands are frequently padded on both sides with NOP (no operation) computer instructions, which are a form of pointer.
When the precise memory range is uncertain, the padding on both sides is used. The malicious instruction will be executed if the hacker’s specified address falls within the padding.
The hacker’s buffer overflow vulnerability techniques are determined by the target’s architecture and operating system.
The extra data they transmit to a program, on the other hand, is likely to contain malicious code that allows the attacker to perform more operations and send new commands to the application.
An attacker who understands a program’s memory structure may be able to purposefully input data that the buffer cannot store. This will allow them to replace executable code in memory regions with malicious code that will allow them to take control of the application.
Injecting new code into software, for example, might send it further instructions that grant the attacker access to the organization’s IT infrastructure.
An attacker uses a buffer overflow vulnerability to corrupt a web application’s execution stack, run arbitrary code, and seize control of a machine.
Buffer overflow flaws can be found in both application servers and web servers, particularly in online applications that use graphics libraries.
Buffer overflow vulnerabilities can also occur in the programming of custom web applications. This is more likely because security teams pay less attention to them, but they are less likely to be detected by hackers and more challenging to exploit.
Attackers use several forms of buffer overflow attacks to gain access to a company’s systems. The following are the most common:
The most prevalent type of buffer overflow attack is this one– when an attacker transmits malicious code data to an application, the data is stored on a stack buffer by the program.
This overwrites the contents on the stack, including the return pointer, giving the attacker control of the transfers.
It is more difficult to carry out a heap-based assault than a stack-based attack. It entails flooding a program’s memory area with data that isn’t needed for current runtime operations.
A format string exploit occurs when an application treats input data as a command or fails to check input data properly. This allows the attacker to run code, read data from the stack, and trigger application segmentation faults.
This could lead to new acts that endanger the system’s security and stability. Now that you are introduced to the different types of buffer overflow attacks let’s look at some examples.
Consider an application that asks for the user’s password before granting access to the system. The valid password grants the user root capabilities in the code below. The application will not grant access privileges if the password is incorrect.
However, because the gets() function doesn’t verify the array limits, there is a risk of buffer overflow in this software.
Here’s an example of what an attacker might be able to do with this coding flaw:
Even though the user had submitted an invalid password, the application grants root rights to the user in the case above.
In this scenario, the attacker provided an input that was longer than the buffer could store, resulting in a buffer overflow that overwrote the memory of the integer “pass”.
As a result, despite the wrong password, the value of “pass” became non-zero, granting root capabilities to the attacker.
Buffer overflows can be avoided by including security features in development code, adopting programming languages with built-in protection, and thoroughly testing code to discover and correct mistakes.
One of the most popular ways to avoid buffer overflows is avoiding standard library functions that haven’t been bounds-checked, such as gets, scanf, and strcpy.
Another typical way to prevent buffer overruns is to implement bounds-checking at runtime. This ensures that the data pushed to a buffer is inside the proper bounds automatically.
Modern operating systems now include runtime protection, which adds an extra layer of defense against buffer overflows. This contains standard safeguards such as:
Buffer overflow attacks frequently require knowledge of where executable code is placed. This is where address space layout randomization (ASLR) comes in. ASLR shifts around data areas at random to randomize address spaces, making overflow attacks nearly impossible.
This method flags memory sections as executable or non-executable, preventing an attack from running code in non-executable regions.
Attackers may try to overwrite the structured exception handling (SEH), a built-in mechanism for managing hardware and software exceptions.
They accomplish this by overwriting the exception registration record, which is kept on the program’s stack, using a stack-based overflow attack.
SEHOP prevents malicious programs from attacking the SEH and exploiting its overwrite exploitation mechanism.
Security measures around development code and operating systems are insufficient to protect an organization’s systems. When a buffer overflow flaw is detected, it’s critical to fix the software as soon as possible and make it available to all users.
There are many methods one can use to prevent buffer overflow attacks. Here are some strategies that should be used in tandem to ensure maximum protection from threats.
Most operating systems make use of runtime protection. Like preventing a typical buffer overflow, runtime protections use address space layout randomization (ASLR), Data Execution Prevention, and Structured Exception Handling Overwrite Protection (SEHOP).
Vendors regularly patch or issue software patches and updates to fix stack buffer overflow vulnerabilities that have been recently discovered. However, there is a period of risk between the vulnerability or exploit being discovered, and a patch or fix being deployed by the vendor.
Only provide users and applications with the permissions they need to conduct their jobs or complete their given tasks. Following the POLP method decreases the risk of a buffer overflow attack.
Only provide users and programs with temporary privileges and then remove them once the work is accomplished.
Buffer overflow attacks are most commonly successful when applications fail to manage memory allocations and validate input from the client or other processes.
Applications written in C or C++ should avoid using non-bounds-checked standard library functions like gets, scanf, and strcpy.
Instead, they should use libraries or classes created to perform string and other memory operations securely. Better still, use a programming language like Java, Python, or C# to decrease the buffer overflow odds.
Any user input and data from unreliable sources should always be validated in-house mobile and web applications to ensure they are within the expected bounds and avoid unnecessarily long input values.
Before deployment, every application security policy should require vulnerability testing for input validation and buffer overflow vulnerabilities.
Circa Las Vegas
Thurs. Aug 5th
Cybersecurity Reunion Pool Party at BlackHat 2021