Buffer Overflow Explained

Buffer overflows present a security challenge where a program exceeds the designated capacity of an adjoining memory block (buffer), overwriting those specific locations. As a result, buffer overflows often result in arbitrary code execution or program crashes.

In the case of stack-based buffer overflows, the focus is on the overwrite of areas allocated on the stack. The stack serves as a memory region dedicated to storing a software’s local variables and return addresses. Exploiting this vulnerability enables attackers to redirect a program to execute potentially harmful code.

In other words, a buffer overflow occurs when an attacker intentionally bombards a data field with inputs that exceed its selected capacity in the assigned temporary storage (buffer). Hence, this deliberate overload causes the excess inputs to spill into the adjacent memory space of the buffer. The ramifications of this attack are severe, including data overwrites, leaking sensitive data, and malware installations. Furthermore, buffer overflow attacks also enable an attacker to potentially take over the target system remotely.

 

How do buffer overflows occur, and why are they dangerous?

Cyber attackers worldwide discover and exploit newly found weaknesses in applications, websites, and underlying system architectures daily. At the same time, memory-based programs are integral to the functionality of new and old electronic devices. As a result, hackers leverage this ubiquity to identify vulnerabilities in program memory and exploit them to execute buffer overflow attacks.

While not a novel phenomenon, buffer overflow vulnerabilities and the corresponding attacks have been a persistent threat to the digital world. For example, in November 2022, Google released a critical update for Chrome to address a zero-day vulnerability. Attackers exploited this high-severity vulnerability that has been present since the start of 2022, and Google described the security flaw as a heap buffer overflow. The incident exemplifies a buffer overflow attack, where attackers manipulated heap data to exploit the program’s (Chrome) functionality.

Here is how a buffer overflow attack occurs. As previously mentioned, a buffer overflow arises when the volume of data surpasses a memory buffer’s assigned storage capacity. Thus, the program attempting to copy data onto the buffer overrides the allocated storage spaces of neighbouring memory locations.

Consider a scenario where a buffer designed for login credentials can handle a password and username input of up to 10 bytes. In such a case, if a transaction involves an input of 14 bytes (exceeding the expected size by 4 bytes), the application may extend the data beyond the designated buffer boundary, causing a buffer overflow.

Unfortunately, buffer overflows pose a risk to all types of software and typically stem from either incorrect inputs or insufficiently allocated buffer space. When a transaction overwrites executable code, the software may exhibit unpredictable behaviour, leading to incorrect outcomes, inaccuracies in accessing the memory, or program crashes.

In addition, some programming languages are more susceptible to buffer overflows. Notably, programs coded using C++ and C are at a heightened risk of being vulnerable to buffer overruns due to the lack of protection measures against acquiring or manipulating memory data. Thus, various operating systems, including Windows, Mac OSX, or Linux, may be more vulnerable as their code often employs one or both of these programming languages.

 

Let’s dig deeper – how can a hacker execute a buffer overflow attack?

When executing a buffer overflow attack, a hacker strategically structures the additional data to be malicious such that it causes harm once it executes. Also, attackers typically engineer the data to issue specific instructions for actions that the malicious actor intends to carry out. These may include initiating responses that corrupt system files, modify program data, or disclose sensitive data.

The sequence of a buffer overflow attack unfolds as follows:

  • The malicious actor transmits meticulously constructed input to a software program. The input is referred to as arbitrary code.
  • The target system attempts to store the entered data in a buffer that lacks sufficient storage capacity.
  • The program then copies the extra data into neighbouring memory locations, thereby overwriting present data.
  • The original data within the buffer includes a return pointer, indicating the address where the process was intended to continue.
  • However, the attacker can manipulate the parameters to redirect the process to a different address.
  • Typically, the hacker adjusts the values to indicate the exploit payload’s location.
  • Subsequently, this alteration redirects the processes’ execution path, relinquishing control to the attacker’s malicious code.

 

The leading causes of buffer overflow attacks

The leading cause of buffer overflows can be attributed to the oversight of software developers in conducting bounds testing. During development, developers must be meticulous in reviewing segments of code that use buffers. Specifically, they must be keen on functions that handle user input. Consider the following code snippet:

 

char $userid[10];

printf("Enter Userid is:");

gets(userid);

 

In this program, it displays ‘Enter Userid is:’, prompting users to input ‘user-id’ with a maximum size of 10 characters. Once the user enters the data, the program stores it in the $userid variable.

However, the provided code illustrates the absence of bounds verification. While the developer specified the variable as 10 bytes long, there are no enforced limits within the function. As such, this oversight exposes the system to potential buffer overflow attacks.

Furthermore, the developer assumes a user will input a proper name like ‘ConwayBill.’ However, if a user enters ‘ConwayBill**************,’ the program is likely to malfunction instead of prompting for valid input.

As aforementioned, programming languages like C or C++ lack built-in bounds verification. Consequently, the program copies the initial 10 bytes into the memory storage location allocated for the userid variable. However, the surplus characters then overwrite the subsequent bytes of RAM, a phenomenon known as ‘stack smashing.’

Now that said, how can you detect buffer overflows in the source code? First, you must possess a deep understanding of how the code works. Furthermore, you must perform a thorough examination of external inputs, buffer manipulations, and functions susceptible to buffer overflow—especially gets(), strcpy(), strcat(), or printf(). Failing to examine and implement these functions with caution may expose your program to buffer overflow attacks in the future.

 

Best practices for preventing buffer overflows

The most effective strategy for thwarting buffer overflow attacks is addressing vulnerabilities at the source code level during the initial development phase. Therefore, to enhance security and deter hackers from capitalizing on potential buffer vulnerabilities, adhere to the following recommended practices:

 

1.   Validating user inputs

When developing programs, consistently validate user inputs to mitigate potential buffer overflow vulnerabilities. Failure to validate assumptions about user-supplied inputs creates security loopholes. Hence, conduct thorough checks on the size and content of data. Additionally, restrict the copying of bytes to designated memory addresses to prevent buffer overflow vulnerabilities from occurring.

 

2.   Implement least privilege for enhanced security

Granting applications the minimum necessary privileges is a fundamental security practice. Whether for applications or users, permissions should strictly align with the tasks and responsibilities at hand. Adopting a least-privilege or zero-trust strategy diminishes the risk of buffer overflow attacks.

For example, consider a scenario where a command prompt window shares privileges with a compromised application. Limiting the privileges of the window reduces the potential for an intruder to exploit the computer through the compromised application.

Also, allocate time-bound permissions to individuals or applications and promptly revoke them upon task completion. This approach enhances security by minimizing the potential impact of security breaches.

 

3.   Protect the operating systems at runtime

Modern operating systems offer various runtime protection mechanisms to safeguard applications from buffer overflow attacks within the OS environment. IT managers can activate these measures during runtime to bolster system security.

  • Data Execution Prevention (DEP): DEP identifies memory regions as executable or nonexecutable. Thus, enabling this measure prevents adversaries from executing instructions stored in a data area through a buffer overflow.
  • Address Space Layout Randomization (ASLR): ASLR introduces randomness to the address space coordinates of crucial data areas within a process, including the stack, heap, and libraries. Randomizing address space coordinates complicates attackers’ attempts to reliably access specific memory functions, making it challenging for them to overflow malicious code into these vulnerable spaces.
  • Structured Exception Handler Overwrite Protection (SEHOP): Structured Exception Handling (SEH) manages hardware and software exceptions. In a buffer overflow attack, hackers may attempt to rewrite the SEH. However, SEHOP acts as a safeguard, preventing malicious code from compromising the integrity of the SEH.

 

4.   Leverage OS features for executable space protection

Employing operating system features that safeguard executable spaces protects against buffer overflows. Specifically, protecting executable spaces prevents code execution in designated memory areas, such as the stack. In a buffer overflow scenario, an attacker might inject arbitrary code into a program’s memory. However, with executable space protection, any attempt to execute this injected code triggers an exception.

For example, specific operating systems and CPUs support features like NX (No eXecute) or XD (eXecute Disabled). These features allow users to specify data pages, including the stack and memory, as writable and readable while preventing execution.

 

About AppCheck

AppCheck is a software security vendor based in the UK, offering a leading security scanning platform that automates the discovery of security flaws within organisations websites, applications, network, and cloud infrastructure. AppCheck are authorized by the Common Vulnerabilities and Exposures (CVE) Program as a CVE Numbering Authority (CNA).

 

Additional Information

As always, if you require any more information on this topic or want to see what unexpected vulnerabilities AppCheck can pick up in your website and applications then please get in contact with us: info@appcheck-ng.com.

Get started with Appcheck

No software to download or install.

Contact us or call us 0113 887 8380

Start your free trial

Your details
IP Addresses
URLs

Get in touch

Please enable JavaScript in your browser to complete this form.
Name