Talos Vulnerability Report

TALOS-2018-0616

Yi Technology Home Camera 27US p2p_tnp cleartext data transmission vulnerability

October 31, 2018
CVE Number

CVE-2018-3947

Summary

An exploitable information disclosure vulnerability exists in the phone-to-camera communications of Yi Home Camera 27US 1.8.7.0D. An attacker can sniff network traffic to exploit this vulnerability.

Tested Versions

Yi Technology Home Camera 27US 1.8.7.0D

Product URLs

https://www.yitechnology.com

CVSSv3 Score

9.0 – CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H

CWE

CWE-319: Cleartext Transmission of Sensitive Information

Details

Yi Home Camera is an internet-of-things home camera sold globally. The 27US version is one of the newer models sold in the U.S., and is the most basic model out of the Yi Technology camera lineup. It still, however, includes all the functionality that one would expect from an IoT device, such as the ability to view video from anywhere, offline and subscription-based cloud storage, and ease of setup.

When the Yi Camera communicates with the ‘Yi Home’ phone app, in order to provide video feeds and status updates, the network daemon in charge is the p2p_tnp binary. This daemon provides network discovery, authorization, and also settings manipulation functionality, all over UDP.

To quickly sum up this issue, a huge portion of the functionality of this device is unencrypted. This simple fact leads to a multitude of issues and vulnerabilities. Any communications between any two devices mentioned in this advisory are potentially vulnerable to a MITM attack, whether it be replaying or modification of traffic, or a similar attack. (The only real exception to this is playing video data, which will be covered later on.) Two different scenarios will be presented, as they both entail different risks: when the Yi Home Camera and its controlling phone are on different subnets and when they are not.

Also, a quick side note, anything that happens through the cloudAPI binary is encrypted over HTTPS to the api.*.xiaoyi.com domain (this changes based on region).

Without rehashing the entire p2p_tnp protocol, it is sufficient to note that many settings can be changed from the owner's phone, with 173 different opcodes being listed inside of the Yi Home application APK. As of the current version of the Yi Home Camera, only 45 of these opcodes lead to valid cases within the p2p_tnp binary, all of which would be vulnerable to an attacker with MITM access on the phone/app's subnet.

Even in a situation where MITM'ing is not possible (e.g. Dynamic Arp Inspection, static arps, or being on a different subnet) utilizing unencrypted traffic for p2p_tnp leads to more potential vulnerabilities, since an attacker can hop onto another user's session by brute forcing port numbers.

Moving on from this scenario, let us examine the more concerning of what occurs when the phone and camera are on different subnets. Three IP addresses are semi-hardcoded into the camera's persistent /tmp/mmap.info settings, which are used for remote cloud communications. As of version 1.8.7.0D the IP's are as such:

server_ips = ["13.228.10.214",
                      "52.204.188.171",
                      "52.9.248.75"]

The camera will send the same UDP packet to all three addresses, first starting with the MSG_DEV_LGN_KEY (\x14) message, which contains the device ID of the camera, and a timestamped nonce and HMAC SHA1 signed version of the nonce. Impersonating a camera cannot happen without knowing the DID and secret key on the device, so even with UDP, this portion is somewhat secure, as the nonces cannot be replayed either (although since there's no signing of the data itself, the message could be edited via MITM). A sample message looks as such:

    buf = "\xf1"  # opcode
    buf += opcode
    buf += "????"
    buf += MY_real_DID
    buf += "\x00"*(0x14-len(MY_real_DID)) # padding for len(DID)=>0x14
    buf += struct.pack(">I",0x02d2020e) 
    buf += "\x00\x02" # Nat type
    buf += MyLittleEndianPort
    buf += MyLittleEndianIP  # port LE, IP LE
    buf += "\x00" * 8 # more padding
    buf += nonce_raw
    buf = buf.replace("????",struct.pack(">H",len(buf)-6))
    return buf

After logging in, keepalives are sent back and forth, but eventually, upon request by a Yi Home app that's not on the same subnet, the remote Yi authentication servers will inform the camera of a new IP address that will act as the bridge between the phone and app. As of the current version, the IP is usually "173.153.82.163" for the camera, and “173.73.4.202” for the phone.

The above situation requires some work from the phone, though. The same MSG_DEV_LGN_KEY message is sent to any of the same servers, however, no SHA1 HMAC nonce is required, so the only thing needed is the DID of the camera. A sample DID consists of a prefix, serial, and suffix. For example, TNPUSAC-112233-NMEDP. After this is sent, the remote servers inform the phone of the remote bridge “173.73.4.202” mentioned above, as well as the UDP port that the communications occur over. Once this is done, all UDP traffic sent to this port is piped over to the camera.

Of huge concern at this point is that, while we cannot brute-force the DIDs for any given device (even though only the suffix and serial number are unique), since UDP is in play, it would be sufficient to constantly probe the remote bridges “173.153.82.163” and “173.73.4.202” for open UDP ports, such that an attacker could talk with whatever was on the other side, potentially leading to other vulnerabilities being exposed in the p2p_tnp daemon.

Also of obvious concern is that all UDP traffic flows over the broader internet, unencrypted. This includes nonces used for authentication (which are vulnerable to replay attacks), MP4 audio stream data from the camera which is completely unencrypted, and anything else sensitive that may have been missed.

It is worth noting that the MP4 video data (not audio) is encrypted with an AES key regenerated on every reboot of the camera, and then shared with the Yi servers. Eventually, the phone is able to view the data.

Timeline

2018-06-13 - Vendor disclosure
2018-09-03 - Vendor submitted build to Talos for testing
2018-09-05 - Talos confirmed issue patched
2018-10-22 - Vendor released new firmware
2018-10-31 - Public release

Credit

Discovered by Lilith ¯\_(ツ)_/¯ of Cisco Talos.