CVE-2018-3947
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.
Yi Technology Home Camera 27US 1.8.7.0D
9.0 – CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H
CWE-319: Cleartext Transmission of Sensitive Information
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.
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
Discovered by Lilith ¯\_(ツ)_/¯ of Cisco Talos.