Firmware Vulnerabilities You Don’t Want in Your Product
BugProveBugProve
Firmware vulnerabilities refer to security weaknesses or flaws found in the firmware of a device. Firmware is a type of software that is embedded within hardware devices and provides low-level control and functionality.
It acts as a bridge between the hardware and the higher-level software. These vulnerabilities can be exploited by attackers to gain unauthorized access and to control or manipulate the device.
Over the past decade, we have witnessed numerous security breaches targeting commercial and industrial IoT devices. For instance, cybercriminals were able to turn off the heating in two buildings in the Finnish city of Lappeenranta, and other attacks such as Shamoon, New York Dam, and the Mirai Botnet have affected industrial IoT devices such as Deutsche Telekom Routers, resulting in the disruption of services.
Although it was widely known that security was a weak point in IoT devices, little progress had been made to address this issue until last year, when Russia attacked Ukraine. The attack demonstrated the real power of cyber attacks, with Anonymous hacking the Kremlin CCTV system and Russia attacking the Ukrainian power grid.
Following these incidents, the US and the European Union have expressed interest in regulating IoT/IIoT cybersecurity posture, which is a much-needed step. However, the question remains: Where should we start, and what are the most dangerous vulnerabilities that can lead to such attacks?
Is there a silver bullet that can protect manufacturers from these attacks? Let's take a look at some of the most dangerous vulnerabilities and their potential mitigations.
Most IT professionals are familiar with the concept of Remote Code Execution (RCE), which is one of the most feared firmware security threats. If an attacker can exploit an RCE vulnerability, they gain complete control of the device or devices and can potentially create a botnet.
Additionally, attackers can steal user data or engage in espionage against various manufacturers. Essentially, an attacker can achieve any outcome they desire.
The question arises: How can attackers find RCE vulnerabilities in devices, and what types can lead to RCE?
Let’s see the most common ones.
We will deep dive into each of these.
Authentication is a crucial aspect of security in embedded systems. It ensures that only authorized individuals can access the device and its functionalities.
Authentication bypass refers to a situation where an attacker can access a device without providing the necessary authentication credentials, such as a username and password. This security vulnerability allows attackers to gain control of the device and its functionalities, potentially causing harm to the device or accessing sensitive data.
There are various techniques that attackers can use to bypass authentication. One standard method is by exploiting default or weak passwords. Many IoT devices have default login credentials that are widely known and can be easily found online.
Attackers can use this information to access the device without going through the authentication process. They can also use brute-force attacks to guess weak passwords.
Another method to achieve authentication bypass involves exploiting firmware vulnerabilities. For instance, this can occur by utilizing a vulnerable version of open-source software or using a logical bug in the authentication flow.
Additionally, network vulnerabilities can be exploited to bypass authentication. Attackers can intercept network traffic to capture login credentials or use man-in-the-middle attacks to impersonate the device and bypass authentication.
It is essential to change the default login credentials and use strong passwords. Strong passwords should contain uppercase and lowercase letters, numbers, and symbols and be 12 characters long.
Secondly, keep up to date on all of 3rd party open-source components you use in your product.
Thirdly, securing the network is crucial in mitigating authentication bypass. This can be achieved by implementing secure communication protocols, such as HTTPS or TLS, to encrypt network traffic. Lastly, conduct penetration tests regularly on every new product release.
Buffer overflow is one of the most well-known and prevalent vulnerabilities in software systems. These vulnerabilities can occur due to various reasons. One common cause is the lack of input validation in a program, which allows an attacker to input data that is larger than the allocated buffer size.
This can lead to a situation where the excess data overwrites adjacent memory locations, resulting in unexpected behavior or crashes. Another cause of buffer overflow vulnerabilities is the use of unsafe functions that do not perform bounds checking, such as strcpy and strcat. We will demonstrate a buffer overflow bug in a real-life scenario.
To do so, we will use DVRF (Damn Vulnerable Router Firmware) as our target. After dropping the firmware into our platform, it will extract the image and decompile every binary to search for potential vulnerabilities.
We chose this target because it is accessible to everybody, and we do not want to compromise any publicly available manufacturer's firmware.
As we see here, the program takes two integer arguments, param_1 and param_2, and declares a local variable called local_200 of type undefined2 (a 2-byte or 16-bit, unsigned integer). It also displays an array called auStack510 of size 502 bytes.
The program then uses the memset() function to set all the bytes in auStack510 to zero. After that, it checks whether the value of param_1 is less than 2. If it is, the program prints a usage message and exits with an error code 1.
If param_1 is greater than or equal to 2, the program prints a welcome message and copies the contents of a string pointed to by the second argument _(*(char)(param_2 + 4))_** into local_200 using the strcpy() function. This is where the buffer overflow vulnerability lies.
If the string pointed to by the second argument is longer than 16 bytes (the size of local_200), the strcpy() function will write past the end of the local_200 buffer and overwrite the contents of the adjacent auStack510 buffer.
This can lead to unpredictable behavior, including crashing the program or allowing an attacker to execute malicious code from firmware vulnerabilities.
To prevent this type of buffer overflow attack, it is essential to use functions that limit the amount of data written to a buffer, such as strncpy() or snprintf(). Additionally, programs should be compiled with buffer overflow protections, such as stack canaries and address space layout randomization (ASLR, fASLR).
Command injection is an attack where an attacker injects malicious code into a command shell to execute arbitrary commands on the target device. This attack can be carried out in many ways, including through web interfaces, input fields, and APIs.
In firmware, command injection is often carried out through web interfaces or APIs, as these are common ways for users to interact with the device.
The implications of command injection in firmware can be severe. An attacker who successfully injects code into a command shell can execute arbitrary commands on the target device.
This can allow an attacker to gain access to sensitive data, control the device, and even launch attacks against other devices on the network. Additionally, command injection can be challenging to detect, as it often appears as legitimate traffic.
This code appears to be a function called wsc_generate_pin that generates a Wi-Fi Protected Setup (WPS) PIN. The WPS PIN is an eight-digit number used to authenticate a wireless device to a Wi-Fi network.
However, there is a potential command injection vulnerability in this code. The vulnerability arises from using the system function, which executes a shell command. Specifically, the sprintf function is used to construct a command string that is then passed to the system without proper validation or sanitization of the input.
The vulnerable code is the highlighted line:
This code constructs a shell command that writes the value of local_18 to the /dev/random file. If an attacker can control the value of local_18, they can inject additional shell commands into the acStack141 buffer, leading to arbitrary code execution. Since this variable came from the user (WPS Pin), this vulnerability is exploitable.
To prevent this vulnerability, it is essential to properly validate and sanitize all input used to construct shell commands. Input validation can be done using regular expressions or whitelist filtering.
Whitelist filtering involves defining an allowed set of characters or values that the input can contain. Developers should also limit the number of characters the input can have to prevent buffer overflow attacks, as discussed above.
We understand that IoT security is a significant challenge, and many manufacturers face difficulties hiring security professionals in this field. By implementing the mitigation techniques mentioned above, you can take substantial steps toward securing your devices.
Additionally, we highly recommend using compilation-time hardening flags as the easiest initial step in the security improvement journey.
Conducting regular security audits and testing is also essential to identify any potential vulnerabilities and address them promptly. To achieve this, we recommend utilizing third-party security labs or, at the very least, using firmware analyzing tools.
The Most Comprehensive IoT Newsletter for Enterprises
Showcasing the highest-quality content, resources, news, and insights from the world of the Internet of Things. Subscribe to remain informed and up-to-date.
New Podcast Episode
Recent Articles