A Guide to Memory Corruption Vulnerabilities in the Linux Kernel
Cyberattacks are primarily motivated by financial gain, which leads attackers to come up with new techniques to access data continuously. Despite the constant rise in the frequency and complexity of such attacks, memory corruption vulnerabilities remain the primary issue that has persisted for four decades.
Administrators can take advantage of their understanding of memory corruption to protect their infrastructure against cyber attackers actively. This guide aims to provide administrators with the necessary knowledge to comprehend memory corruption and its aftermath in case of vulnerability exploitation.
What are Linux Kernel Vulnerabilities?
The Linux kernel is vulnerable to a variety of memory issues. The following memory-based vulnerabilities are where attackers focus and are the foundation for many of the security patches released every month. If you have ever wondered why a specific vulnerability requires a critical patch, these issues can lead to severe data breaches.
A buffer overflow happens when developers fail to validate variables before assigning data to them. When the data exceeds the defined capacity of the variable, an “overflow” occurs, allowing an attacker to inject their own code into adjacent memory space. Without proper data validation, a buffer overflow could result in an attacker gaining root access or being able to execute remote code.
Since Linux is written in C, it is vulnerable to buffer overflow, unlike other programming languages such as Python and Java, which are not vulnerable to overflow attacks.
CVE-2023-0179 is an example of a buffer overflow vulnerability. This issue could allow the leakage of both stack and heap addresses, and potentially allow Local Privilege Escalation to the root user via arbitrary code execution.
Developers define the maximum value that can be stored in an integer variable based on the data type used. For instance, a 32-bit unsigned integer variable can store values ranging from 0 to 4,294,967,295, whereas a signed integer can store values between −2,147,483,648 and 2,147,483,647. However, if the code adds a value that exceeds the maximum limit of the variable, an “overflow” occurs, leading to unexpected results.
For example, if a statement tries to add 1 to a variable storing the value 2,147,483,647, the result will be a negative value of -2,147,483,648. Similarly, if a negative integer overflows, it will result in a positive number. The behavior for unsigned integers depends on the programming language used, but in the case of the C language, the results are often unpredictable.
CVE-2022-0998 is an integer overflow vulnerability found in the virtio device driver code of the Linux kernel. A local user can use this flaw to crash or potentially escalate their privileges on the system.
Developers and server administrators often find memory corruption in the Linux kernel to be a challenging issue. Such corruption can lead to unpredictable behaviors, and in some cases, no errors are thrown. This issue arises when developers unintentionally alter data in memory or modify pointers that point to specific memory locations where data is stored.
CVE-2023-1073 is an example of a memory corruption vulnerability discovered in the human interface device (HID) subsystem of the Linux kernel. A local attacker can use this flaw to crash or potentially escalate their privileges in the system.
Denial of Service
Distributed denial-of-service (DDoS) attacks are widely known, wherein attackers leverage multiple hijacked devices to inundate a target with traffic, resulting in server crashes.
However, any attack that interferes with a service is known as a denial-of-service (DoS) attack. Improper memory management often causes memory-based DoS attacks, known as resource exhaustion attacks. These vulnerabilities can be detrimental, leading to critical service crashes affecting thousands of users if they exist on servers.
CVE-2023-1390 is an example of a remote denial of service vulnerability discovered in the TIPC kernel module of the Linux kernel. This flaw allows a remote attacker to cause a denial of service.
NULL Pointer Dereference
In C programming, a pointer is a variable that stores the memory address of a value, rather than the value itself. This allows developers to manipulate the value stored at a specific memory location, even if the variable associated with that location is out of scope.
A NULL pointer dereference takes place when an application tries to access a memory location through a pointer that it assumes to be valid, but is actually NULL. This can lead to the application crashing or terminating unexpectedly.
CVE-2022-47929 is a NULL pointer dereference vulnerability found in the Linux kernel’s network queuing discipline implementation. This vulnerability allows a local attacker to cause a denial of service (system crash).
When a function uses a variable to modify or create data, the variable itself must first be initialized with a value. If the variable is not assigned a value, it’s considered uninitialized and causes undefined behavior if referenced in the program.
Undefined behavior from uninitialized data is difficult to detect as C compilers are not required to diagnose or throw an error. Most developers work with testing or fuzzing tools to identify uninitialized data that could cause undefined error issues.
CVE-2022-29968 is an example of a use-before-initialization vulnerability found in the Linux kernel where the io_uring subsystem lacks initialization of kiocb->private. This flaw allows a local attacker to expose sensitive information (kernel memory).
What are the most hazardous memory vulnerabilities?
Every year, MITRE publishes its Top 25 Most Dangerous Software Weaknesses report. Note that this report includes web-based attacks, but the three most common and hazardous memory vulnerabilities are:
- Buffer overflows
- Integer overflows that lead to a buffer overflow
- Pointer dereference (missing pointer check)
All three vulnerabilities can lead to severe data breaches. Memory corruption vulnerabilities have been responsible for some of the largest data breaches to date. One important finding from a recent intelligence report is that about 72% of attacks are application-specific and web application attacks. An attacker can identify issues in the code and create an exploit to take advantage of the vulnerability as open-source programs are frequently included in dependent code or are the main application itself.
The report’s third interesting statistic is that 21% of attacks target the technology sector. Sensitive information must be stored, networked, protected, and transferred by the technology sector. By focusing on this sector, attackers might get access to the infrastructure that stores data and discreetly abuse it, possibly exposing the company for months.
How do you identify memory corruption vulnerabilities?
Memory corruption is typically a result of developer errors, but in scenarios where multiple applications are running on a single machine, identifying which application is causing issues can be challenging. One way to identify errors in Linux is to check the system logs, where the operating system detects any issues.
For example, Linux reserves the first 64 KB of memory for the BIOS, and any modifications made to this memory space are scanned by the operating system. If Linux detects any changes made to this reserved memory, it logs a warning for administrators to address the issue.
As Linux is an open-source operating system, many memory-based vulnerabilities are reported by researchers. One such recent discovery is the “BleedingTooth” vulnerability, which enables attackers with the bd address of a target machine to crash it, causing a denial-of-service (DoS), elevating privileges, and possibly gaining access to encryption keys.
Security researchers use various tools and techniques to find bugs in software, including carefully reviewing code and using scanning tools such as fuzzing to trigger errors that can be reported to developers. After identifying vulnerabilities, developers patch the code, and a security update is released to address the issue.
How do you fix memory corruption?
Fortunately, Linux has implemented several security features to help combat memory corruption, including Kernel Address Space Layout Randomization, Control Flow Integrity, and Kernel Page Table Isolation. Despite these mitigating features, however, the operating system and its dependencies are still vulnerable to attacks.
Mitigation techniques vary depending on the vulnerability found, but temporary solutions often involve disabling a critical component. For example, during the Heartbleed incident, administrators could disable the heartbeat used in OpenSSL to communicate between client and server. While this temporarily solved the issue, any application that required a heartbeat signal from the server would have experienced unexpected results, such as crashes or denial of service.
However, temporary mitigation techniques are not permanent, and patches must be applied to stop exploiting the vulnerability permanently. Security patches update the code, but they require a system reboot, resulting in downtime. As a result, system administrators often delay patching vulnerabilities until a maintenance window is available, leading to some of the most significant data breaches to date.
How to Protect Your Infrastructure from Memory Corruption Vulnerabilities?
Since administrators are left to the mercy of developers, it’s essential that they take the right steps to stop attackers. You might not control the code, but administrators can take the right steps to minimize the network’s attack surface and avoid being the next target. Here are a few ways administrators can stop memory-based attacks:
- Run vulnerability scans regularly. Vulnerability scans will identify issues including those already reported publicly. When a vulnerability is found, a patch can be installed.
- Perform thorough testing of any third-party applications before promoting them to a production server.
- Use KernelCare’s live patching to quickly apply the latest security patches without the need for a reboot.
Detecting memory-based vulnerabilities is challenging, and immediate patching is crucial to provide optimal protection against errors. KernelCare Enterprise offers a live patching service that eliminates the need for administrators to delay patching. It automatically patches various versions of Linux without downtime or disruption, ensuring that critical infrastructure is not left open to vulnerabilities while waiting for a maintenance window.