C is regarded as the programming language used in the IoT ecosystem. According to IoT Analytics’ State of the IoT 2021 report, the most popular programming language for IoT is C. It is the choice of nearly half of the developers surveyed mainly because of the low-level control it provides, high performance, wide microcontroller platform support, and portability.
This popular programming language comes with a simple but significant weakness. Its ‘free()’ function can be exploited by threat actors. Invoking this function multiple times can lead to unwanted and possibly damaging consequences.
The Double Free problem
The ‘free()’ function in C programming languages is intended for the deallocation of memory that was previously allocated using the 'malloc()’, ‘calloc()’, ‘realloc()’, ‘valloc()’ and other memory allocation functions. It releases the memory back to the system so it can be available for later use.
For instance, if a dynamically allocated memory for an array using malloc() has been allocated, it can be released by calling ‘free()’ on the pointer to the allocated memory. Doing this supposedly prevents memory leaks that can cause the consumption of high amounts of memory that may lead to crashes and other issues.
The irony is that the ‘free()’ function can also be the reason why a memory leak emerges. Calling this function twice or more times can create undesirable outcomes, particularly vulnerabilities that can be exploited by threat actors to write values to arbitrary memory spaces and generate an interactive shell that comes with dangerously elevated privileges.
This is the Double Free (CWE-415) problem. It is a software bug that is increasingly threatening the IoT ecosystem and IoT device users. When a program tries to free the same memory location twice or more times, arbitrary code execution and other malicious activities can happen. It can allow hackers to take control of IoT devices and obtain sensitive information such as personal data, passwords, and secrets. In some cases, threat actors can exploit the vulnerability to undertake DDoS attacks and spread malware. Also, it is possible to experience memory corruption.
How a double free occurs
Double free occurs due to poor memory management practices. Many organizations need policies or rules on how they deal with memory allocation. Prime examples of such problematic memory management practices are as follows:
Memory freeing or clearing is not as simple as deleting a file to free space for a new file to occupy. There are complex mechanisms that spring into action. If the ‘free()’ function is invoked on a buffer, what happens is that free buffers are reordered and free memory blocks are put together to create bigger buffers that will be available for future use. Memory blocks are set in a double-linked array that points to the next and previous blocks.
The key action here is the linking/unlinking of unused buffers. Calling the ‘free()’ function, as mentioned above, causes the linking of free memory. Doing it again causes the unlinking of some memory blocks as a new double-linking is established with previous and next blocks that have been rearranged with the initiation of the ‘free()’ function.
A common consequence of a double free is the crashing of a program. This happens because the unlinking of an already free memory causes the program to access an uninitialized or invalid memory. A double free also results in the revision of the flow of execution of a program, causing unpredictable behavior or malfunctions.
Moreover, double or multiple memory freeing may enable arbitrary code execution. This is more dangerous and can happen because the vulnerability may allow a hacker to write to a memory block and overwrite important data or hijack the flow of execution. One example of this is the CVE-2022-37332 vulnerability in the Foxit Software (News - Alert) PDF Reader. This enabled exploitation of the media player's ability to reuse a previously freed memory and subsequently execute an arbitrary code.
How to prevent a double free
The first and arguably the most important way to address the double free problem is to have good memory management practices. The main goal is to prevent the freeing of memory that has not been allocated and the freeing of memory that has already been freed by another application.
Attaining an infallible memory management system is virtually impossible though. Good memory management techniques like garbage collection and the use of smart pointers do not guarantee that no vulnerabilities will emerge. Regular software or firmware updating, which is one of the most sensible solutions, is also far from ideal. It should be done, but it does not eliminate the risk of the problem’s emergence.
Secure coding, thorough code testing, prompt firmware updating, and proper memory management are a must, but they are not enough. IoT device manufacturers, in particular, usually only rely on firmware updating for the security of their products. Many do not have secure coding and code testing practices. Many also do not have proper memory management, since their apps are mostly derived from open-source or freely available software.
However, it is possible to address the double free threat by using a separate platform or tool that can provide runtime protection or conduct something similar to runtime application self-protection (RASP) in IoT devices. This can block memory and code manipulation attacks by ensuring that memory leaks are spotted and the underlying causes resolved.
The best way
The ideal solution to the threat posed by the double free vulnerability is the prevention of the conditions that make it happen. However, given the many limitations when it comes to writing secure code and undertaking continuous thorough code security testing, the best solution for most organizations is to use a well-designed platform or tool that can provide RASP-like protection to IoT devices.
The double free vulnerability problem is mostly a problem that should be resolved by IoT product makers. With the rise of laws and regulations aimed at forcing IoT manufacturers to ensure the security of their products, it is incumbent upon them to ascertain that the software used in their devices has proper memory management and secure code to avoid having a double free vulnerability.
About The Author:
Joydeep Bhattacharya is a technology enthusiast. He loves to write on topics related to IoT, data science, artificial intelligence, metaverse, and other future focussed technologies.