If you prefer to read this in Japanese, download the Japanese version!
Through our ongoing device security analysis, we often uncover—and responsibly disclose—new unknown vulnerabilities in both closed and open source software components used in connected devices. In this blog post, we discuss a directory traversal vulnerability that we recently discovered while analyzing the firmware of a device based on the BlackBerry QNX operating system.
First, here’s a quick background explanation of directory traversal vulnerabilities: directory traversal is a method of attack that exploits legitimate file system access processes in devices. A vulnerability exists if an attacker can craft a file path input when requesting access, such that she will gain unintended access to sensitive files and directories. Such attacks can lead to the compromise or theft of sensitive applications and data on the device, or even allow attackers to modify the device’s behavior by adding malicious code to the device.
Some network services which are common in connected embedded devices, such as simple HTTP and FTP servers, can be imagined as translators of incoming network packets to file access operations (Fig. 1). In this context, some of the data sent to the device from the network (which could possibly be malicious) flows to a file operation and is interpreted as a file path to be read.
To detect directory traversal vulnerabilities in such web services, we follow the path of operations performed on the data in the received network packet and divide them into logical sections. This path must include code sections which sanitize the input and enforce rules regarding the permitted locations of files to be read. We can try to locate these code sections automatically and, if they are not found or are observed to be improperly implemented, this may be regarded as indicating a potential vulnerability in the program.
Figure 1: Information flow by code sections. a: Naïve program where the received file name is not validated prior to use. b: Expected pattern where the received file name is validated prior to use
While preparing for our upcoming support for BlackBerry QNX, a POSIX-compliant microkernel-based operating system (OS) that is widely used in the automotive industry, we came across QNX Slinger which is a simple HTTP server included in older OS versions (up to 6.6). We analyzed it using the process described above and found that the data flow was somewhat different than the expected pattern (Fig. 2). After it was received from the network, the file name to be accessed was indeed sanitized to remove the possibility to include “/../” and to prevent accessing locations outside the designated HTML content folder. However, after the file name is sanitized, it undergoes another operation – URI decoding.
Figure 2: Data flow between packet reception and file access as observed in QNX Slinger 1.0.
While the order between these two operations may look insignificant and could easily be accidentally changed, it has important security consequences. This flow introduces the possibility of inserting “/../” into the file name by using its encoded equivalent (“/.%2e/”) in the packet. Because the encoded version is not considered in the sanitize operation, an attacker can use it to perform directory traversal, escape the designated HTML directory and read other files in the system, as shown in Fig. 3.
Figure 3: Simple directory traversal by using /.%2e/ instead of /../ allows fetching arbitrary files from the filesystem.
Moreover, since Slinger has CGI functionality, the same flaw can be used to remotely execute programs on the system, escaping from the designated CGI script directory by including “/.%2e/” in the name of the script to be executed in the same way as detailed above. In this case, “/” characters in the file name would be interpreted as separators between the script name and its parameters which would interfere with the attacker’s ability to go down the directory tree. However, the segment performing the separation between the script name and the parameters is also located before the decoding stage, allowing the attacker to use “%2f” instead in order to reach any location in the file system. Luckily, after opening the listening socket, Slinger runs with minimal permissions (user id -2) which limits the impact of this flaw. Nevertheless, some operations can still be performed. In the image below you can see how we execute /usr/sbin/logger with a parameter of our choice, and as a result the system’s syslog is indeed updated (Fig. 4).
Figure 4: Demonstrating remote code execution. Above: A single TCP packet containing directory traversal from ~/cgi-bin to /usr/sbin/logger, encoded using “%2f” instead of “/” and “%2e” instead of “.”. Below: Configuration of slinger server and the impact of the packet above which shows the logger is indeed executed.
The described bug results from the validation step not being adjacent to the file access/system command operation. Logical bugs of this kind can easily be introduced through subtle code changes, even by experienced software engineers. Such bugs cannot be described in local terms so finding them requires approaches which allow the researcher to consider different parts of the code and their functionalities along the interesting data flow paths. At Vdoo, we explore several approaches for automated in-depth analysis of software in binary form in order to provide our holistic solution for evaluating complete firmware images in the security context.
Complete remediation of the vulnerability will require updating the Slinger component, however, following the security precautions detailed in Slinger’s configuration guidelines will reduce its impact in many cases. At Vdoo, we believe that adherence to the security guidelines of all the components present on the system will have crucial influence on real-world attack scenarios, and precise automated verification of security guidelines and standards must be an essential checkpoint in the development cycle of embedded devices.
The vulnerability described above has been responsibly disclosed to BlackBerry which dealt with the issue promptly and professionally. We would like to thank the BlackBerry PSIRT team for their cooperation and for setting a high standard for vendor responsibility. The vulnerability has been issued CVE-2020-6932 with CVSSv3 10. For additional details, please refer to the BlackBerry advisory page.