Buffer Overflows: Difference between revisions

From Elvis Wiki
Line 108: Line 108:


Stack canaries are small random values placed on the stack to detect and prevent buffer overflow attacks. If an overflow occurs and modifies the stack, the canary value will change, triggering a security alert or crash. <ref name=”RE1”/>
Stack canaries are small random values placed on the stack to detect and prevent buffer overflow attacks. If an overflow occurs and modifies the stack, the canary value will change, triggering a security alert or crash. <ref name=”RE1”/>
To '''disable stack canaries''' when compiling a program, use the -fno-stack-protector option with gcc:
To '''disable stack canaries''' when compiling a program, use the -fno-stack-protector option with gcc:
<pre>
<pre>

Revision as of 10:15, 11 December 2024

Introduction

Buffer overflow is a security vulnerability that should not be underestimated, as it has been the most common type of vulnerability in the last decade. This type of attack is an essential part of all security attacks, as buffer overflow vulnerabilities are widespread and easy to exploit. Especially in the field of cyber attacks, they are exploited by users to gain access to vulnerable servers and control them.

Definitions

Buffer

A buffer is defined as a limited, contiguously allocated set of memory. The most common buffer in C is an array. [1]

Buffer Overflow

Buffer Overflows are possible because in the C and C++ languages there exists no inherent bounds-checking to ensure that data being copied into a buffer will not be larger than what the buffer was initialized to hold. Consequently, if the person writing the program has not explicitly coded the program to check for oversize input, it is possible for data to fill a buffer, and if that data is large enough, to continue to write past the end of the buffer. [1]

Common Weakness Enumeration (CWE)

The importance of addressing buffer overflow vulnerabilities can be seen by examining Mitre’s respective parent category: [2]

  • CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer

There is a large variety of direct and indirect child categories that further help create a taxonomy of the issues at hand. Some of those are listed here: [3] [4]

  • CWE-788: Access of Memory Location After End of Buffer
  • CWE-787: Out-of-bounds Write
  • CWE-786: Access of Memory Location Before Start of Buffer
  • CWE-125: Out-of-bounds Read
  • CWE-120: Buffer Copy Without Checking Size of Input (’Classic Buffer Over- flow’)
  • CWE-121: Stack-based Buffer Overflow
  • CWE-122: Heap-based Buffer Overflow
  • CWE-126: Buffer Over-read

History

In the past, there were often a series of events executed with the help of buffer overflows. In 1980, the term Internet worm was a very well-known and sensitive topic because a worm was malicious software that reproduced itself and spread through network connections. It was called a Morris worm because on November 2, 1988, an event occurred that changed the way people thought about networks and about the Internet. On that day, tens of thousands of computers quickly and simultaneously became infected with a self-replicating computer program. Back then, computer science student Robert T. Morris created a computer worm that exploited an unsafe function, which at the time was very commonly used and distributed. Through the practical application of a buffer overflow, the computer worm spread itself around at an alarming rate and, going back, nearly shut down the entire internet. This situation resulted in Morris being the first person convicted under the Computer Fraud and Abuse Act, demonstrating further how dangerous buffer overflows can be. To this day, this attack is perhaps one of the most significant events in the history of computing. With buffer overflows, it was also possible to bypass various security measures. For example, buffer overflows could be used to remove software restrictions from firmware or to bypass copy protection. This was the case with the Android and iOS operating systems, where it was possible to remove various locks and modify the smartphone according to one's own wishes. For example, it was possible to install apps that were not available in the store elsewhere, change the boot animation, access hidden system files, remove manufacturer-specific apps, remove network locks, and much more. One keyword is "jailbreaking" for Apple devices and "rooting" for Android devices. On Nintendo's game console, a game called Pokemon Yellow could be changed from the inside by manipulating the program using shellcode.

While many of these events already reside in the past, buffer overflows do not. The exploit reoccurs frequently, so much so that in 2023 they still secured themselves a spot on the Common Weakness Enumeration/SANS list of the Top 25 Most Dangerous Software Errors. Whether through the adaptation of the exploit's mechanism or simply by focusing on a new set of targets, buffer overflows stay relevant. That's why, when dealing with cybersecurity of any sort, there is no way past them.

Technical Background and Context

Memory Layout of a Process

The Stack and Important Control Structures

Causes

Dangers

Types of Buffer Overflow Vulnerabilities

Buffer Over-Read

Buffer Over-Write

Integer Overflow

Integer overflows occur when an arithmetic operation attempts to generate a value that lies outside a range that can be represented with a specified number of bits. The most common result of an overflow is that the least significant representable bits of the result are stored. An overflow condition can lead to results that are equivalent to unintended behavior. In particular, if the possibility is not expected, an overflow can affect the reliability and safety of a program. A code example is shown below.

unsigned char a = 255;
unsigned char b = 2;
unsigned char Result = a + b;

The data type unsigned char is used, which comprises 8 bits, and the value range is from 0 to 255. For the variable "a," the value 255 is assigned, and for the variable "b," the value 2 is assigned. If an arithmetic operation is performed, we would get a result that requires more bits than are present to represent. The corresponding dual calculation is shown below.

  11111111 (a)
+ 00000010 (b)
----------
 100000001 (Result)

The front one, the ninth bit, is no longer contained in the 8 bits of the data type unsigned char. If only the last 8 bits were considered, the result would be 1 and not 257.

Stack-based Buffer Overflow

Heap-based Buffer Overflow

Use-After-Free Vulnerability

The Use-After-Free bug is a vulnerability where memory should not be used in this way while the program is running. If a program clears memory, but the pointer to that memory is not yet cleared, an attacker can use this bug to gain access and control.

Mitigation Techniques and How to Disable Them

This chapter will only briefly touch on the subject of Mitigation Techniques. Firstly, it will explain the basic terms in a rudimentary way and provide short guides to disable some mitigation techniques for research purposes.

Adress Space Layout Randomisation (ASLR)

ASLR randomizes the memory address space layout of processes, making it harder to predict the location of specific functions or buffers. [1] Since code reuse attacks (e.g., ROP attacks) require the memory addresses of gadgets to be known to an attacker, techniques to randomize their entry points have become increasingly popular.

ASLR can be temporarily disabled at the system level (Linux):

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

Re-enable after testing:

echo 2 | sudo tee /proc/sys/kernel/randomize_va_space

Non-executable Stack (nx-stack)

A non-executable stack, or nx-stack, prevents execution of code in the stack, when designated as non-executable, mitigating buffer overflow attacks that inject shellcode into that region. [1]

To disable nx-stack on a program, use the -z execstack option during compilation. This allows execution of code in the stack memory:

gcc -z execstack -o vulnerable_program source.c

Data Execution Prevention (DEP)

Data Execution Prevention (DEP) is a security feature originally developed by MicrosoftR© for Windows XP SP2. There are two basic variants: hardware-based DEP and software-based DEP. If supported by the CPU as well as the process, hardware DEP will be employed; otherwise, DEP has to be carried out in software, which is part of the Windows operating system. The basic functionality of DEP is to prevent applications from executing code in a non-executable area of memory.

Stack Canaries

Stack canaries are small random values placed on the stack to detect and prevent buffer overflow attacks. If an overflow occurs and modifies the stack, the canary value will change, triggering a security alert or crash. [1]

To disable stack canaries when compiling a program, use the -fno-stack-protector option with gcc:

gcc -fno-stack-protector -o vulnerable_program source.c

Conclusion

Since the rise of C in the early 1970s, buffer overflows have become a serious security vulnerability. Even though high-level programming languages are typically not affected, the number of vulnerable systems is actually rising. At the same time, a wide array of countermeasures are also increasingly adopted and applied. Features like executable space protection (e.g., data execution prevention under Windows) have already been deployed since the mid-2000s, and on the compiler side, technologies like Stackguard support several detection and prevention mechanisms (e.g., different types of canaries). Furthermore, almost every widely used operation system supports Address Space Layout Randomization in order to minimize the attack surface for buffer overflow attacks. For example, at the beginning of 2020, most of the bigger operating systems (Linux, Windows, macOS, iOS, Android, Solaris, OpenBSD, etc.) will offer support for ASLR.

Another key point is the expansion of the Internet of Things (IoT). These widely distributed networks of hardware endpoints have deemed themselves the perfect target for buffer overflow attacks. This stems from the fact that IoT applications mostly utilize low-level, closely hardware-related languages such as C and C++, both of which are almost exclusively for buffer overflows.


References

  1. 1.0 1.1 1.2 1.3 1.4 C. Anley, The Shellcoder’s Handbook: Discovering and Exploiting Security Holes, 2nd ed., Indianapolis: Wiley, 2007
  2. MITRE, "CVE Search Results for 'buffer overflow'," [Online]. Available: https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=buffer+overflow. Accessed: Oct. 16, 2024.
  3. MITRE, "CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer," [Online]. Available: https://cwe.mitre.org/data/definitions/119.html. Accessed: Oct. 16, 2024.
  4. MITRE, "CWE-788: Access of Memory Location After End of Buffer," [Online]. Available: https://cwe.mitre.org/data/definitions/788.html. Accessed: Oct. 16, 2024.