Back to the articles
Firmware vulnerabilities you don’t want in your product
Table of contents
Why are firmware vulnerabilities important?
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. In a previous blog post, we collected 7 questions and answers about firmware in general.
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, both 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? In this blog post, we will cover some of the most dangerous vulnerabilities and their potential mitigations.
Vulnerabilities' Holy Grail – RCE
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 is able to exploit an RCE vulnerability, they gain full 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 that arises is: how can attackers find RCE vulnerabilities in devices, and what types of vulnerabilities can lead to RCE?
Let’s see the most common ones.
- Authentication Bypass: Attackers can bypass authentication mechanisms in IoT devices that utilize weak or default passwords. In certain cases, they can exploit logical bugs or circumvent specific security checks. Several techniques can result in an authentication bypass, including default passwords, brute-force attacks, network vulnerabilities, or firmware vulnerabilities.
- Buffer Overflows: A buffer overflow vulnerability occurs when a program tries to store more data in a buffer than it can hold, causing the data to overflow into adjacent memory locations. An attacker can exploit this vulnerability by crafting input data that overflows the buffer and overwrites adjacent memory locations with malicious code.
- Injection Flaws: Injection flaws occur when an attacker is able to inject malicious code into an IoT device through unsecured inputs or interfaces, such as a web form or API.
We will deep dive into each of these.
Authentication Bypass
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 gain access to 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 common method is by exploiting default or weak passwords. Many IoT devices come with default login credentials that are widely known and can be easily found online. Attackers can use this information to gain access to the device without having to go 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 an open-source software or by exploiting 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.
Authentication Bypass Mitigation
Firstly, it is essential to change the default login credentials and use strong passwords. Strong passwords should contain a mix of uppercase and lowercase letters, numbers, and symbols, and be at least 12 characters long.
Secondly, keep up to date all of your 3rd party open source components that 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 test regularly on every new product releases.
Buffer overflow
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 (which is a 2-byte, or 16-bit, unsigned integer). It also declares 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 of 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, all stemming from firmware vulnerabilities.
Buffer overflow mitigation:
To prevent this type of buffer overflow attack, it is important to use functions that limit the amount of data that can be 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 injections
Command injection is a type of attack where an attacker injects malicious code into a command shell in order to execute arbitrary commands on the target device. This type of attack can be carried out in many different 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 difficult 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 the use of the system function, which executes a shell command. Specifically, the sprintf function is used to construct a command string that is then passed to 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/urandom file. If an attacker is able to 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.
Command injection mitigation
To prevent this vulnerability, it is important to properly validate and sanitize all input that is 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 that the input can have to prevent buffer overflow attacks, as discussed above.
Conclusion
We understand that IoT security is a significant challenge, and many manufacturers are facing difficulties in hiring security professionals in this field. By implementing the mitigation techniques mentioned above, you can take significant 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.