Memory Safety: CISA and NSA guidance on CWE-1399

Memory Safety Vulnerabilities

Memory safety is a complex topic, and it is important for developers to understand the risks of memory safety vulnerabilities and how to prevent them because they are a major problem for software security. They are estimated to be the cause of 70% of all security vulnerabilities, and have been used in some of the most famous cyberattacks in history, such as Heartbleed and WannaCry. Memory safety vulnerabilities are a class of software bugs that occur when a program incorrectly accesses memory. This can lead to a variety of problems, including:

  • Data corruption: If a program writes to the wrong memory location, it can overwrite other data that the program needs to function correctly. This can lead to crashes, unexpected behavior, or even security vulnerabilities.
  • Code execution: In some cases, memory safety vulnerabilities can allow attackers to inject their own code into a program. This code can then be used to steal data, install malware, or take control of the system.

Most common types of memory safety vulnerabilities

  • Buffer overflows: A buffer overflow occurs when a program writes more data to a buffer than it has space for. This can overwrite other data in memory, leading to data corruption or code execution.
  • Dangling pointers: A dangling pointer is a pointer that refers to a memory location that has been freed. If a program tries to use a dangling pointer, it can lead to a crash or unexpected behavior.
  • Use-after-free: A use-after-free vulnerability occurs when a program tries to use a memory location that has been freed. This can lead to data corruption or code execution. 

A basic C example demonstrating a buffer overflow vulnerability

#include <stdio.h>

int main() {
    char buffer[5];  // Buffer with a capacity of 5 characters

    printf("Enter your name: ");
    fgets(buffer, 100, stdin);  // Unsafe input: allows up to 100 characters

    printf("Hello, %s", buffer);

    return 0;
}

Explanation

  1. Buffer declaration: The buffer array is declared with a size of 5 bytes, meaning it can hold a maximum of 4 characters plus the null terminator.
  2. Unsafe input: The fgets function is used to read input from the user. However, it's instructed to read up to 100 characters, which is much larger than the buffer's capacity.
  3. Potential overflow: If the user enters a name longer than 4 characters, the excess characters will be written beyond the bounds of the buffer array, overwriting adjacent memory locations.

The program might crash immediately if critical data is overwritten. An attacker could exploit this vulnerability to inject and execute their own code, and sensitive data stored in memory could be modified or stolen as a result.

Notable real-world examples

1. Heartbleed (CVE-2014-0160)

  • Type: Buffer overflow in OpenSSL, a widely used cryptographic library.
  • Impact: Allowed attackers to steal sensitive information, including passwords and private keys, from servers using vulnerable OpenSSL versions.
  • Fixed: Patches were released for OpenSSL in 2014.

2. WannaCry (CVE-2017-0144)

  • Type: Use-after-free vulnerability in Microsoft Windows' Server Message Block (SMB) protocol.
  • Impact: Enabled ransomware to spread rapidly and encrypt files on affected systems, demanding ransom payments for decryption.
  • Fixed: Microsoft released security updates in 2017.

3. Meltdown (CVE-2017-5754) and Spectre (CVE-2017-5753, CVE-2017-5715)

  • Type: Hardware vulnerabilities affecting most modern processors, allowing attackers to steal sensitive data from memory.
  • Impact: Affected a wide range of devices, including personal computers, servers, and cloud infrastructure.
  • Fixed: Mitigations were released through software updates and hardware microcode updates.

4. Double-Free (CVE-2019-9810)

  • Type: Use-after-free vulnerability in the Chrome web browser.
  • Impact: Allowed attackers to execute arbitrary code on affected systems.
  • Fixed: Google released a security update for Chrome in 2019.

5. Null Pointer Dereference in Internet Explorer (CVE-2020-0674)

  • Type: Null pointer dereference vulnerability in Internet Explorer.
  • Impact: Allowed attackers to execute arbitrary code on affected systems.
  • Fixed: Microsoft released a security update for Internet Explorer in 2020.

6. Memory Corruption in Apple macOS (CVE-2021-30869)

  • Type: Multiple memory corruption vulnerabilities in macOS.
  • Impact: Allowed attackers to execute arbitrary code with kernel privileges on affected systems.
  • Fixed: Apple released security updates for macOS in 2021.

7. Prototype Pollution in Node.js (CVE-2022-21824)

  • Type: Prototype pollution vulnerability in the Node.js JavaScript runtime environment.
  • Impact: Allowed attackers to execute arbitrary code or cause denial-of-service attacks on affected systems.
  • Fixed: Node.js released security updates in 2022.

Prevention and Mitigation

There are a number of ways to prevent memory safety vulnerabilities. One way is to use a memory-safe programming language, such as Java or Rust. These languages have built-in features that help to prevent memory errors. Another way to prevent memory safety vulnerabilities is to use careful coding practices, such as using bounds checking and avoiding pointer arithmetic.

  • Bounds checking: Always validate user input to ensure it doesn't exceed buffer limits.
  • Safer input functions: Use functions like fgets with appropriate size limits, or consider alternatives like.
  • Static analysis: Use tools that can detect potential buffer overflows during compilation.
  • Runtime protections: Employ techniques like AddressSanitizer to detect buffer overflows at runtime.

CISA and NSA Guidance

Transitioning to Memory Safe Programming Languages (MSLs) can eliminate these vulnerabilities, reducing the need for these costly activities and leading to safer products. The U.S. Cybersecurity and Infrastructure Security Agency, along with other international cybersecurity authorities, developed guidance urging software manufacturers to prioritize MSLs. This guidance includes creating memory safe roadmaps to eliminate these vulnerabilities, a move requiring top-down leadership and resource realignment.

To quote some statistics from the advisory:

  • About 70 percent of Microsoft common vulnerabilities and exposures (CVEs) are
    memory safety vulnerabilities (based on 2006-2018 CVEs).
  • About 70 percent of vulnerabilities identified in Google’s Chromium project are
    memory safety vulnerabilities.9
  • In an analysis of Mozilla vulnerabilities, 32 of 34 critical/high bugs were memory
    safety vulnerabilities.10
  • Based on analysis by Google’s Project Zero team, 67 percent of zero-day
    vulnerabilities in 2021 were memory safety vulnerabilities.

The document recommends the following Memory Safe Languages in the Apendix. Other than Python and Rust, all these languages have been created by well-known tech companies. The main memory unsafe languages still in use are C and C++.

  • C# (Microsoft): 
  • GO (Google)
  • Java (Sun/Oracle)
  • Python (Guido van Rossum)
  • Rust (Mozzila Foundation)
  • Swift (Apple)

You can read the source document here.

Updated Jan 04, 2024
Version 2.0

Was this article helpful?

No CommentsBe the first to comment