December 19, 2022
Embedded devices running C code are often to exposed to two common security weaknesses that can be exploited to modify the device memory, resulting in memory leaks, denial of service, unauthorized code execution, etc. These weaknesses are:
In this post, I`ll do a deep dive into each of these two weaknesses and provide some hypothetical and real-life examples of how they could be exploited.
What Is the Double Free (CWE-415)?
- Program crashes - one of the most common impacts of a double free vulnerability is a program crash. When a block of memory is freed twice, it can cause the program to access invalid or uninitialized memory, which can result in a crash.
- Changing flow of execution - the double free vulnerability can cause the flow of execution in a program to change unexpectedly. This can occur when the memory that is freed twice is accessed by multiple variables or pointers, which can lead to unpredictable behavior.
- Arbitrary code execution - in some cases, a double free vulnerability can be exploited by an attacker to execute arbitrary code. This can occur when the vulnerability allows the attacker to write to memory in a way that allows them to overwrite important data or control the flow of execution.
In many cases, an attacker who manages to write values to arbitrary memory spaces can create an interactive shell with elevated privileges. This is also known as a write-what-where condition.
What happens when a buffer is “freed”?
Double Free Examples
Note that to illustrate the double free problem, we are showing simplified examples. In real life, double free vulnerabilities are much more complex and might be laid out across hundreds of lines of code and multiple files.
The following is a trivial example of a double free vulnerability.
Complex Example with Two Functions
Let’s now look at an example where the vulnerability exists in two different functions.
What Is a Use After Free (CWE 416)?
In a C or C++ memory is allocated when program instructions are executed. The ‘heap’ is the memory space available to programmers to allocate and deallocate for program instructions.
Referencing memory after it has been “freed” may cause a program to crash. Using memory allocated on the heap after freeing or deleting it results in undefined system behavior, most commonly a write-what-where condition (ability to write arbitrary values to memory spaces).
A use after free error occurs when the program continues to use the pointer after it has been freed. This is typically caused by error conditions at the application level, or confusion over which program elements are responsible for freeing memory (e.g. lack of coordination between different modules of the same program).
Use after free errors can have the following impacts:
- Availability—can cause a program to crash. E.g., If the program attempts to merge blocks with previously freed data, and invalid data is used as block information, the operating system process can be disrupted.
- Integrity—program data could be corrupted as a result of the error (more details below).
- Code execution—the error can lead to a write-what-where condition, which can potentially be used to execute arbitrary code.
How does data corruption occur?
In a use after free error, memory might be effectively allocated to another pointer at some point after it was freed. The original pointer to the freed memory is reused and points somewhere in the new allocation. When the data changes, the validly used memory is destroyed. This causes undefined behavior in the process and can lead to data corruption.
How does arbitrary code execution occur?
When memory space is freed and then reused, if the newly allocated data might hold a class, multiple function pointers might exist within heap data. If an attacker manages to overwrite one of those pointers with an address to shellcode, they could execute arbitrary code.
Use After Free Examples
No security concept can protect the contents of specific memory blocks and ensure that only certain pointers can use them. A program’s memory space is entirely available for all pointers anywhere within the program.
Hypothetical Example: Dangling Pointer
If a program uses a dangling pointer to freed memory blocks, it can still access everything stored in these locations. If someone subsequently reallocated the memory to another part of the program that manages sensitive data, it could accidentally change or disclose the data.
Here is an example of C code that uses a dangling pointer:
CVE-2022-21661: WordPress SQL Injection Flaw
In January 2022, WordPress released a patch for the CVE-2022-21661 vulnerability. Attackers could exploit this use after free vulnerability to launch an SQL injection attack.
CVE-2022-226617 Use After Free Fix In iOS 15.4
Another example was in March 2022 when Apple launched iOS 15.4—the new release included a fix for the CVE-2022-22667 vulnerability in GPU drivers. This vulnerability enabled applications to execute arbitrary code using kernel privileges.
CVE-2022-23270: Windows Server VPN Remote Kernel Use After Free Vulnerability
This vulnerability was discovered in the Windows kernel through reverse engineering and fuzz testing of the raspptp.sys kernel driver. The vulnerability allows attackers to perform denial of service (DoS) and potentially achieve remote code execution against a target server. CVE-2022-23270 is dependent on the specific implementation of the Winsock Kernel (WSK) to be successfully triggered.
CVE-2022-37332 : Foxit Software PDF Reader
Mitigating CWEs 415 and 416 With Sternum
The vast majority of IoT/embedded devices use C code, and are prone to related memory and code vulnerabilities, including 'double free' and 'use after free' exploit attempts.
Sternum’s patented EIV™ technology protects from these with runtime (RASP-like) protection that deterministically prevents all memory and code manipulation attempts, offering blanket protection from a broad range software weaknesses (CWEs)—including 415 and 416.
Embedding itself directly in the firmware code, EIV™ is agentless and connection agnostic. Operating at the bytecode level, it is also universally compatible with any IoT device or operating system (RTOS, Linux, OpenWrt, Zephyr, Micirum, FreeRTOS, etc.) and has low overhead of only 1-3%, even on legacy devices.
Moreover, EIV’s runtime protection features are also augmented by (XDR-like) threat detection capabilities of our Cloud platform, leveraging its extended observability features. For a quick overview, check the video down below:
Sternum offers you :
- Agentless security—integrates directly into firmware, making it a part of the core build. This ensures that the solution cannot be externally compromised and leveraged as a point of failure.
- Automatic mitigation of known and zero-day threats—prevents 96.5% attacks in benchmark (RIPE) security tests. Its vulnerability-agnostic approach makes it equally effective in dealing with known and zero-day threats. This not only improves security but can also cut security patch management costs by as much as 60%.
- Supply chain protection—relies on binary instrumentation, making it able to protect all running code. This extends to 3rd party and operating system libraries, effectively preventing all supply chain exploit attempts.
- Protection of isolated devices—does not rely on external communication to secure devices, making it equally effective for connected and isolated devices.
- Live attack information with zero false positives—real-time alert system notifies about all blocked attacks, providing—for each—detailed logs and attack path analysis. The deterministic nature of EIV’s integrity checks ensures that all alerts are always valid.
- Advanced threat intelligence—leveraging AI anomaly detection and granular device-level understanding of user interactions, user activity, and device behavior. Can automatically spot indicators of exposure and compromise, malicious behavior, security blindspots, stealthy and sophisticated threats.
- Streamlined compliance—helps meet the latest cyber regulations for IoT devices (IEC 62443, FDA, NIST, etc) and the most current FBI recommendations for Internet of Medical Things (IoMT) endpoint protection.
Better Performance with Autonomous Observability
Gain complete visibility by monitoring and analyzing events in your device or across an entire fleet, from the first line of code and until post-deployment maintenance.
Diagnose software bugs and vulnerabilities by using instrumentation, to pinpoint flaws, gain dynamic profiling and analysis of the software, including third-party code.Learn about Sternum observability >>