Are IoT Devices Putting Your Products at Risk of A Cyberattack?

Are IoT Devices Putting Your Products at Risk of A Cyberattack?

Part 2: A Technical Breakdown

In Part 1, we dove into the problem and understood how poorly secured or compromised WiFi systems can introduce dangerous weaknesses in your product security posture. Here, in Part 2, we’ll dive into the technical “how” this vulnerability was discovered and exploited. 

C20 Binding process

The binding process is the first interaction between the user and the device. This moment creates an opportunity for a threat actor to infiltrate the network while the user is learning the binding steps. The process is required in order to:

  1. Associate the camera with the specific user
  2. Deliver WiFi credentials to be used for connectivity 

Upon initial device turn-on, the camera does not have any WiFi credentials to perform a connection to the remote server and it will enter “listening” mode. When the user performs the binding process via the mobile app, the WiFi credentials (access point name and password) must be securely sent to the camera for it to connect to the server.

The task of communicating credentials to a device outside of the network (in this case, the user’s phone, will be connected to the WiFi but the camera is initially not) is achieved by data frame length encoding.

Data frame length encoding takes advantage of the property of data frames in 802.11 WPA and WEP encryption where the encryption process will render the data unreadable but will always append a fixed-length header to the frame and thus, even though the contents of the data frame cannot be read, the length of the original packet can be deduced.

This technique is now fairly common and is implemented with some differences in protocols such as SmartConfig and AirKiss.

High level visualization of the binding process:

Weakness in the binding process

A soft spot in wireless binding processes, such as the one performed in the C20 camera, is the broadcasting of the credentials over the air for the new device to capture and use (step 4 in the diagram below). This stage is inherently sensitive since malicious actors can capture the credentials the same way the camera does, or send credentials the same way the phone or AP does. This is why special care is taken to encrypt and/or obfuscate the sent credentials as much as possible.

In the case of the C20 camera binding process, there was an effort to encrypt and obfuscate the credentials in a significant way. The full process of the credentials broadcasting from the phone app side is described below:

Xiaomi C-20-2

As mentioned in the diagram above, the credential data goes through two stages before being sent over the air. 

The first is encryption using AES128 CFB, which in itself is considered secure for most purposes in case the encryption key is not trivial. The second stage is encoding the encrypted credentials in a 6-bit byte array which serves as further obfuscation in case the payload is captured with no knowledge of the process used to create it. But, this process is easily reversible and will not deter a malicious actor by itself.

So, it seems like the strength of the entire security mechanism hangs on the strength of the AES128 key used for encryption.

Looking at the key in the application log extracted from the mobile device it seems like the key being used is long and diverse in such a way to make it sufficiently strong.

Xiaomi C-20-3

The key is then used to encrypt the WiFi credentials in the payload creation process before sending them over the air.

Xiaomi C-20-4

The camera should be able to intercept the payload and decrypt correctly. Since AES is a symmetric encryption algorithm, it requires the camera to have access to the same key used to encrypt the payload.

This is still a very secure encryption scheme if the encryption key used is unique to the camera since it will require brute-forcing– a large number of passwords in order to decrypt credentials sent for each camera. In the case of the C20 camera, it was suspected that this is not the case and that the key is shared between multiple devices. The indication for this is that the provided QR code, scanned via smartphone, is the same link for all C20 cameras, instead of providing a unique URL for each. 

In this case, once the key was obtained (as detailed above by logs or other means), it can be used to decrypt credentials sent over the air to other cameras of the same model.

Moreover, it can be determined that the encryption key is not specific per-device but rather, per product model.

Xiaomi C-20-5

And indeed if we retrieve the”.product_secret” from the camera’s flash, create the array as described we get the same key.

Xiaomi C-20-6

Xiaomi C-20-7

It can therefore be determined that the encryption key used to encrypt/decrypt the WiFi credentials over the air is derived from the “.product_secret” parameter and is not unique, which can also be determined from access to any C20 camera device.

Decrypting user credentials sent over-the-air

The process of decrypting credentials sent over the air is performed in two phases:

  1. Capturing the SmartConfig sequence over the air and filtering the data from the transmitted sequence and removing offsets and other spacing bytes.
  2. Decrypting the data to actual credentials

Capturing the SmartConfig sequence

Capturing the data can be achieved by filtering on broadcast 802.11 data frames sent by the home or office router. After obtaining the filtered sequence of SmartConfig, the spacing bytes and headers can be removed to arrive at the actual data array.

The filtering out of non-data bytes can be achieved by reversing the process used to build the SmartConfig sequence as it is done in the “com.aliyun.alink.business.devicecenter” module:

Xiaomi C-20-8

Once retrieving the data bytes, the offset needs to be removed to arrive at the final data bytes array:

Xiaomi C-20-9

Decrypting the data to actual credentials

The AP name is not encrypted, so the AP name can be seen in plain text at the end of the first stage.

The password is encrypted as described in the previous section. We can arrive at the password itself by performing the reverse process of the one used to encrypt and encode the password. This means decoding the 6-bit data array back to an 8-bit data array and then decrypting it using the key we obtained.

Running the following decryption string will yield the original password.

 

from Crypto import Random

from Crypto.Cipher import AES

from pathlib import Path

import re

def six_to_eight_bits_demangler(bytes):

    bits_arr = b''

    byte_arr = b''

    for counter, byte in enumerate(bytes):

        for i in range(6):

            bit = (byte >> i) & 1

            bits_arr += (bit).to_bytes(1, byteorder='big')

    new_byte = 0

    for counter, bit in enumerate(bits_arr):

        new_byte |= bit << (counter % 8)

        if counter % 8 == 7:

            byte_arr += (new_byte).to_bytes(1, byteorder='big')

            new_byte = 0

    return byte_arr

def decrypt(encrypted_byte_array):

    iv = b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'

    key = b'\\x76\\xe0\\x7c\\xa3\\x31\\xe0\\xd0\\xa4\\x40\\x78\\x3c\\xb3\\xaf\\xa4\\xf7\\x6f'

    cipher = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128)

    return cipher.decrypt(encrypted_byte_array)

def decrypt_bytes():

    password_encrypted_string = b'\\x2b\\x3e\\x29\\x1f\\x2b\\x23\\x24\\x23\\x14\\x33\\x08'

    demangled_bytes = six_to_eight_bits_demangler(password_encrypted_string)

    decrypted = decrypt(demangled_bytes)

    print(f'Decrypted password is: {decrypted}')

 

and indeed we receive the password used:

Xiaomi C-20-10

Note: This vulnerability may affect other security camera models, such as C21, EC4 and others.

Mitigations

The vulnerability described above, is a design flaw. No coding mistakes were involved. The feature designer did take into consideration the need to encrypt and obfuscate the credentials before sending them over the air. However, even when using a strong encryption scheme, it will only be as strong as the encryption key it is used with.

It is therefore important to consider the uniqueness of the key we are using, as we saw in the case of the C20 camera, the same key was used for all cameras of the same model, once we extracted the encryption key from one camera, we could use it to decrypt communication of other cameras. This can be avoided if the key is unique. A unique key can be created by using some unique device parameters, either a random number that is created and written to the devices flash memory in the production process or using a unique parameter that already exists on the device such as the devices MAC address. Another mechanism that can be used to create a unique key for communication is the challenge response mechanism.

Summary

During the course of our research of the C20 camera, we identified what looked like a design flaw in the process of encryption of the users WiFi credentials when they are sent to the camera during the binding process. We continued to perform the following steps in order to exploit this vulnerability:

  1. The design flaw was validated by repeating the process with multiple cameras and understanding the QR used by the camera is not unique.
  2. The mobile app was reversed to perform the binding process and the camera’s firmware in order to understand the process. Here we realized the app is encrypting the credentials with a key which was necessarily non-unique since it was derived from the non-unique QR code. 
  3. They key was then extracted from the camera’s flash memory, allowing for the researchers to write a PoC code that decrypts communication based on that key. It was successfully used to decrypt the credentials sent during the binding process of other cameras of the C20 model. 

 

As we determined, the single point of failure in this case was the non-unique key that was used, so don’t only choose your keys wisely, but also, make them unique.