Out-of-Bounds Write: A Software Security Risk

Vivek GalatageVivek Galatage
8 min read

What is a ...

Software Security

Software security refers to the measures and techniques used to protect software systems from attack, exploitation, and other security threats.

It protects the -

  • Confidentiality

  • Integrity

  • Availability of software systems and data

from malicious or unauthorized access, modification, or theft.

Software Vulnerability

Software vulnerability refers to a weakness or gap in a software program that attackers could exploit to compromise the system's security.

These vulnerabilities can arise for various reasons (and not limited to), such as -

  • Poor coding practices

  • Incorrect configuration

  • Design flaws.

Once discovered, attackers can exploit these vulnerabilities to gain unauthorized access, steal sensitive information, or cause damage to the software system.

Out-of-Bounds Write

Bounds

Bounds refer to the limits of an array, buffer, or any other data structure that stores data in a contiguous block of memory.

Illustration

A program writes to memory outside a buffer's bounds in this vulnerability.

Consider the below illustration. Each square represents a memory block, and the train with the top view representing a set of machine instructions reads/writes at each memory block based on the given instructions. There is an end-of-line signal - ๐Ÿšง - to denote that train can't proceed further for a given read/write operation - the end of the buffer marker!

If the instructions are incorrect, a train might be riding past the signal and trying to reach other blocks, adversely affecting the memory blocks out of bounds.

Example

Let's see how this may look in a C program.

#include <stdio.h>

int main() {
    char buffer[10];

    printf("Enter a string: ");
    gets(buffer); // Potential Out-of-Bounds Write

    printf("You entered: %s\n", buffer);
    return 0;
}

The "gets" function reads a string from the user. However, It does not perform any bounds checking, so if the user enters a string too long for the buffer, an Out-of-Bounds Write will occur, potentially overwriting memory used by other parts of the program.

CWE-787

CWE - Common Weakness Enumeration - is a standardized system for categorizing software security weaknesses, and the ID - CWE-787 - refers to an out-of-bounds write error.

๐Ÿ’ก

Boeing Dreamliner 787 โœˆ๏ธ shares the number 787. Easier to memorize, you see!

The CWE publishes the Top 25 vulnerabilities every year, and according to the last few years' data, the CWE-787 has made it to the top spot! No doubt!

The graph depicts the trend of finding CWE-787 in software products over the years! Quite an upward trend! ๐Ÿ“ˆ

Implications

Out-of-Bounds writing can have several potential outcomes

  1. Crashes and program termination

  2. Incorrect results: If the out-of-bounds write operation modifies data unexpectedly, it can lead to incorrect results that might not be immediately obvious.

  3. Memory corruption leads to unpredictable behavior and potential crashes.

  4. Malicious code execution

  5. Denial of Service (DoS) attacks are where the program becomes unresponsive or crashes repeatedly.

Code Execution

When an attacker can control the data that is written outside of the bounds of a buffer, code execution can happen by:

  1. A program receives data from an untrusted source, such as user input or a network connection.

  2. Data is stored in a buffer with the program not having proper bounds checking.

  3. The attacker sends a specially crafted payload that overflows the buffer and modifies the data stored in adjacent memory locations.

  4. The overflow can modify essential data structures, such as the return address of a function, and change the program's code execution path.

  5. The attacker-controlled data is executed as code, allowing the attacker to take control of the target system and execute arbitrary code.

TL; DR

The implications of OOBW can be depicted in below graphic illustration

Mitigation Techniques

To prevent these attacks, software developers need to take a multi-layered approach to security, and each layer has its dedicated roles and responsibilities outlined below.

Application Developer

As an application programmer, you also play a crucial role in preventing OOBW vulnerabilities and other memory-based security threats. Some of the ways you can help include -

Secure Coding Practices

By following secure coding practices and avoiding dangerous programming constructs, such as buffer overflows, you can help prevent OOBW vulnerabilities and other memory-based security threats.

Input Validation

You can prevent buffer overflows and other OOBW vulnerabilities by validating user input and ensuring it is within the expected bounds.

Boundary Checking

By checking the bounds of arrays and other memory structures, you can ensure that writes to memory stay within the allocated space, preventing OOBW vulnerabilities.

Memory Management

By carefully managing memory allocation and deallocation, you can ensure that memory is not corrupted and that buffer overflows do not occur.

Code Review

You can identify and fix security vulnerabilities by performing code reviews and thoroughly testing your code.

๐Ÿ’ก

These and other steps can provide a more secure computing environment for users. Additionally, by following secure coding practices, you can help improve the overall security of the software you develop and contribute to a safer and more secure computing environment for everyone.

Programming Language

The programming language in which an application is written can also prevent OOBW vulnerabilities and other memory-based security threats. Some programming languages include built-in features or libraries that help prevent these types of vulnerabilities, while others may require developers to take additional steps to ensure security.

Memory Safe Languages

Some programming languages, such as Rust or Swift, are designed to be "memory safe," meaning that they prevent common memory-based security threats, including OOBW vulnerabilities, by design. These languages provide automatic memory management and other security features, such as bounds checking and stack protection, that make it more difficult for developers to introduce vulnerabilities.

Bounds Checking

Certain programming languages like Ada provide built-in bounds checking to help prevent OOBW vulnerabilities. In these languages, array bounds are checked at runtime, and an exception is raised if an out-of-bounds write is attempted.

Secure Libraries

Many programming languages provide libraries and other tools to help prevent memory-based security threats, including OOBW vulnerabilities. For example, the C standard library provides functions such as strncat and strncpy, which limit the number of characters written to a buffer, helping to prevent buffer overflows and other memory-based security threats.

Buffer Overflow Protection

Some programming languages, such as C and C++, can be compiled with buffer overflow protection, such as Stack Canaries or Address Space Layout Randomization (ASLR), to make it more difficult for attackers to exploit memory-based security threats.

๐Ÿ’ก

The programming language in which an application is written can impact its security. Developers can take advantage of the security features provided by the language or implement additional security measures to help prevent Out-of-Bounds Write vulnerabilities and other memory-based security threats.

Operating System

The operating system prevents OOBW vulnerabilities and other memory-based security threats. Some of the ways that the operating system can help include:

Memory Management

The OS manages the allocation and deallocation of memory within a process. The operating system can help prevent OOBW vulnerabilities and other memory-based security threats by enforcing strict memory allocation policies.

Address Space Layout Randomization (ASLR)

As I mentioned earlier, ASLR is a security feature that helps protect against memory-based attacks by randomly arranging the memory locations of key data areas, such as the stack and heap, in a process' address space.

Data Execution Prevention (DEP)

DEP is another security feature that helps protect against memory-based attacks by marking certain memory regions as non-executable. This makes it more difficult for attackers to execute malicious code that has been injected into memory, such as by exploiting a buffer overflow vulnerability.

Stack Canaries

Stack canaries are a security feature that helps detect buffer overflow attacks by placing a unique value, known as a "canary," on the stack just before the return address. When the function returns, the value of the canary is checked. If it has been changed, it indicates that a buffer overflow has occurred, and the function terminates, preventing the attacker from executing malicious code.

Sandboxing

The operating system can use sandboxing to isolate applications and restrict their access to sensitive system resources, such as memory and the file system. This makes it more difficult for attackers to exploit vulnerabilities within the application and access sensitive information.

๐Ÿ’ก

By implementing these and other security measures, the operating system can help prevent Out-of-Bounds Write vulnerabilities and other memory-based security threats and provide users with a more secure computing environment.

Tools

Debugging OOBW vulnerabilities can be a challenging experience for developers. These types of vulnerabilities are often the result of a logic error or oversight in the code and can be difficult to detect and reproduce. Here are some common approaches to debugging OOBW vulnerabilities:

Code Review

Reviewing the code manually can help identify potential areas where OOBW vulnerabilities may exist. This process involves looking at the code, understanding how it works, and identifying where it may be vulnerable to memory-based security threats.

Debugging Tools

Debugging tools, such as Valgrind, can identify OOBW vulnerabilities by analyzing the memory usage of a program as it runs. These tools can help identify any memory accesses that are outside the bounds of an array or buffer and can provide information about the source of the problem.

Unit Testing

Writing unit tests that specifically target the code suspected of having an OOBW vulnerability can help detect the vulnerability. For example, tests can be written to verify that the code behaves correctly when a large input is provided or when the input is unexpected.

Fuzz Testing

Fuzz testing is a technique that involves sending random or malformed input to an application to identify vulnerabilities. Fuzz testing can be an effective way to identify OOBW vulnerabilities because it can help identify situations where the code may not be able to handle unexpected input correctly.

TL;DR

Conclusion

Out-of-Bounds Write is a severe threat to software security, and it is important for software developers to be aware of the risks and take steps to prevent these types of vulnerabilities. By implementing proper buffer management techniques and following best practices for secure coding, software developers can help to protect users from the severe consequences of an Out-of-Bounds Write.

Closing Remarks

  • Please visit https://twitter.com/vivekgalatage and follow to get notifications to all such articles in the future.

  • The article illustrations are inspired by the "Spider-Man 2" train scene ๐Ÿ•ท๏ธ

0
Subscribe to my newsletter

Read articles from Vivek Galatage directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Vivek Galatage
Vivek Galatage