The Claroty research team, Team 82, has discovered 10 vulnerabilities in Ruijie Networks Reyee cloud management platform, affecting both the platform itself as well as Reyee OS network devices.
Ruijie specialise in networking devices such as routers, switches, access points, and cloud services for enterprises, educational institutions, government organisations, and service providers with hundreds of thousands of customers across 90 countries including Australia.
Ruijie devices can be found in various settings, for example access points providing free Wi-Fi in airport terminals or shopping malls.
The vulnerabilities, if exploited, could allow a malicious attacker to execute code on any cloud-enabled device, giving them the ability to control tens of thousands of devices.
The story begins with a simple question: How can we hack wireless access points and leverage our way into their internal networks without knowing the Wi-Fi credentials or having physical access to the device?
Publicly available Wi-Fi hotspots such as those in airports and other public places often provide free internet access. Often these connections are not secure and researchers and cybersecurity experts encourage users not to conduct sensitive company or personal business over these networks.
For an attacker, sniffing – and gaining access to – local traffic can be a tempting target. Team82 decided to go one better in its research of Ruijie Networks’ ecosystem and attempted to find vulnerabilities that would allow an attacker to execute arbitrary code on every cloud-connected device. We indeed did find 10 vulnerabilities that if exploited could expose every Ruijie-connected device and pose devastating consequences for its users.
In addition to the vulnerabilities, Team82 devised an attack scenario called Open Sesame. In this attack, an attacker with in close physical proxmity to a Ruijie Reyee access point could exploit leak identifiers over-the-air, and pinpoint attack the device through Ruijie cloud, giving them remote code execution on the device and access to its internal network.
This is another example of weaknesses in so-called internet-of-things devices such as wireless access points, routers, and other connected things that have a fairly low barrier to entry on to the device, yet enable much deeper network attacks.
Ruijie Networks has addressed the 10 vulnerabilities disclosed by Team82 in an update to its cloud infrastructure; no action is required by users.
What is Ruijie Networks
Ruijie Networks is a company specializing in networking infrastructure products for enterprises, educational institutions, government organizations, and service providers. They supply networking devices such as switches, access points, and cloud services to their customers. Ruijie does business in more than 90 countries, employs more than 8,000 people, and claims USD1.6 billion in revenue.
Ruijie devices can be found in various settings, for example access points providing free Wi-Fi in airport terminals or shopping malls.
Team82’s WAN-to-LAN Vulnerability Research
The first step in vulnerability research is to first understand the attack surface and what parts of the ecosystem attackers could exploit. Usually, the attack surface on an IoT device is reduced to the services it exposes, such as an HTTP webserver, remote control services such as SSH or Telnet, or miscellaneous services such as SNMP. Each one of these components could be abused and exploited by attackers, giving them access to your device.
In our case, the attacker is not on the same network as the victimized access point, eliminating the possibility of researching exposed services, all of which are inaccessible from the WAN. Instead of focusing on the services running on the access point, we concentrated on the different components enabling remote access to the device.
We decided to focus our research toward Ruijie’s cloud ecosystem, the Ruijie Reyee cloud platform, with the intention of using the cloud as our entry point into remote devices that are otherwise inaccessible.
-
Ruijie Cloud Management Portal: For starters, Ruijie provides its clients with the ability to remotely manage appliances and networks. This is done through a cloud-based web management portal that is accessible to registered users. This platform also allows users to configure their devices and monitor their operation.
-
Device Provisioning: Once a device is connected to the network, it will try to initiate a provisioning process to Ruijie’s cloud systems that begins with sending a serial number to the cloud. The cloud then validates the serial number and registers the identified device, which can now be claimed by a registered user. In order for a client to interact with the device, it must use the serial number to claim the device. Once claimed, a device can be fully controlled through Ruijie’s management portal.
-
Ruijie’s Access Point Firmware: We purchased a Ruijie access point hoping to be able to research the firmware; some IoT vendors will gate their firmware downloads from users. Ruijie, however, allows firmware downloads from its website. However, when we downloaded the firmware and examined it, we discovered that extracting the actual device firmware would not be simple.
When gaining access to a firmware blob, the first step is usually to examine whether the file is encrypted, or packed. To do so, the simplest method is to check the entropy of the file; if the entropy measured on the file is high, it is very likely encrypted/packed. When we examined the firmware file we downloaded, this was exactly the case.
This meant we could not extract the device filesystem and configuration directly from the firmware we downloaded, and since we found no evidence of compression, we were left to conclude the firmware was encrypted.
However, since we also bought a device, we chose to try to gain shell access through a vulnerability in one of its LAN listening services. This way, we could gain access to the device filesystem, and try to understand the firmware decryption mechanism. An RCE vulnerability later, and a few minutes of searching the device system for the firmware decryption binary netted us with the following binary – rg-upgrade-crypto.
And upon further analysis, we confirmed that it is used to decrypt device firmware during the upgrade process of the device. We confirmed this by matching a magic string in the executable which matched the magic signature of the encrypted firmware file downloaded from the vendor’s website.
Having found the relevant binary for firmware decryption, we tried to use it on the firmware we downloaded. However, since the access point is using a different CPU architecture than most modern PCs (MIPS32), we could not run it directly on our machines.
To execute this binary, we used QEMU, an open source project allowing users to emulate many CPU architectures. So we copied the rg-upgrade-crypto binary, with its shared object dependencies, and used QEMU to run it.
We then used the binary located in the device to decrypt the firmware we downloaded, giving us access to the device firmware and all following firmware versions.
After decrypting the device firmware, we discovered a tar archive that contained three sections:
-
CONTROL: A section containing the hardware version of the firmware
-
Kernel: A section containing the Linux Kernel for the device.
-
Root: A section containing a SquashFS filesystem and all the files, configurations and binaries inside the firmware.
Analyzing Ruijie Device-to-Cloud Communication
After gaining access to the firmware, our next step was to understand how devices connect and communicate with Ruijie’s cloud services. To do that, the first step is always to identify the binary used to communicate with the cloud. To locate this binary, we used different approaches, including checking the startup scripts in the firmware located under /etc/init.d/, searching for strings that would exist inside the cloud binary (for example 0 the cloud endpoint URI), and looking for different configuration files in the system.
After some time, we managed to discover the binary handling most cloud communication: mqlink.elf.
Our next step was to understand how the binary connects to the cloud, and what kinds of messages are sent between the device and the cloud. Usually, vendors choose a protocol for devices to communicate with the cloud, and it is important to identify and understand which protocol is used in each specific case. One way to do that is to search for strings inside the binary/libraries that could point to which protocol is used. Here is a short list of common strings used by different protocols commonly used in device-to-cloud communication:
-
MQTT: paho, mosquitto, mqtt[s]://
-
WS: ws[s]://, Upgrade: websocket
-
VPN: openvpn, .vpn
-
HTTP: http[s]://, GET, POST, URL
In Ruijie’s case, the protocol used is MQTT.
MQTT 101
MQTT is a messaging protocol using a Publisher-Subscriber architecture (Pub-Sub). In this protocol, there is a central entity called a broker that is in charge of distributing messages to all the different clients connected to it. In order to communicate, MQTT clients use a topic, that is essentially a named channel. Using this topic, clients can either subscribe to it, telling the broker to send any message sent over this topic to the client, or publish messages: send a message over this topic.
Apart from the standard aspects of the MQTT protocol mentioned above, MQTT also supports a wide range of authentication/authorization schemes, including credentials-based authentication, and mutual TLS (mTLS) authentication. This way, only valid clients are able to connect to the MQTT broker and distribute/receive messages using it. This is all configured inside the MQTT broker, dictating how clients are able to connect to it.
Ruijie’s MQTT Broker
With a basic understanding of MQTT, we moved on to understand how Ruijie devices connect to Ruijie’s MQTT broker. This is composed of two main things:
-
Identifying Ruijie’s MQTT broker
-
Gaining access to valid Ruijie MQTT credentials/client certificates.
Luckily for us, we identified a configuration file (located under /etc/config/mqlink) which contains the endpoint and port used by Ruijie.
Breaking MQTT Authentication (CVE-2024-45722)
Next, we moved on to understand how devices authenticate to the MQTT broker. The two main schemes for MQTT authentication are either a username/password pair, or client certificate (mTLS). After a short look at the binary, we discovered that in Ruijie’s case, the username/password pair is used. After a short reverse-engineering session, we understood the credential-generation process.
To summarize, first the device takes its serial number, an identifier it reads from a chip and stores in its configuration, and uses it as the MQTT username. Then, it generates the password in the following manner: first it takes the SN, reverses it, and performs a SHA256 calculation on it. This is then used as the password for the MQTT connection.
This means that by knowing a device’s serial number, we could generate its MQTT username/password pair, and authenticate to Ruijie’s MQTT broker on its behalf. The issue is that serial number is not a strong identifier because it usually follows a sequential pattern. To make matters worse, often users/developers leak devices’ serial numbers, which means that these leaks actually leak the devices’ credentials, because they are generated from the same identifier. To showcase this issue, we simply searched for Ruijie access point unboxing videos on YouTube, which netted us with half a dozen serial numbers for real users’ devices.
After having access to a serial number, we implemented a simple Python script to connect to Ruijie’s MQTT broker, and it worked, giving us the ability to authenticate as a device to the MQTT broker.
Ruijie’s MQTT Topic Architecture
After managing to connect to Ruijie’s MQTT broker, our next step was to understand what kind of messages are sent over the various topics.
After some reverse engineering, we created a list of topics devices publish messages to:
-
cloud/sync: Over this topic, devices send keepalive messages and status reports.
-
cloud/config_change: Over this topic, devices notify the cloud about config changes performed on them.
-
cloud/event: Over this topic, devices send event notifications to the cloud, like a reboot event, firmware upgrade etc.
-
cloud/state_change: Over this topic, devices send topology change updates, informing the cloud about connections and disconnects.
In general, devices use these topics to notify the cloud about their existence and upstream events. In addition to these topics, every device subscribes to a certain topic for the cloud to send commands to the device:
-
device/{SN}: the topic devices subscribe to to receive commands from the cloud such as configuration changes, updates etc.
After understanding the topic architecture in the system, we asked a question: Can we subscribe to the topics devices usually publish messages to (cloud/*) ? We tried doing so, and were surprised to find out we could actually subscribe to these topics, and instead of the MQTT broker rejecting our subscription, it bombarded us with tens of thousands of messages from devices worldwide!
When we took a closer look at these messages, we found something even crazier. Inside each message there was the sending device’s serial number, meaning that by subscribing to these topics, we would receive a full list of all cloud connected devices’ serial numbers!
Using the leaked serial numbers, we could generate valid authentication credentials for all cloud-connected devices! This meant that we could perform a wide range of denial-of-service attacks, including disconnecting devices by authenticating on their behalf, and even sending fabricated messages and events to the cloud; sending false data to users of these devices, below.
However, we wanted to leverage our way into remote code execution on all cloud-connected devices, so we set our sights on these types of vulnerabilities next.
RCE On All Cloud-Connected Devices (CVE-2024-52324)
We then analysed what kind of messages the cloud sends to devices. As shown before, in order to send commands to devices, the cloud sends data to the following MQTT topic: cloud/{SERIAL_NUMBER}. This means that every device subscribes to its unique command topic, dictated by their serial number.
Our goal was to see commands the cloud sends to devices, which meant we wanted to subscribe to devices’ unique topics. However, while it is possible to subscribe to ~50,000 topics (mapped to ~50,000 devices with unique serial numbers), it would take a long time and a lot of resources. Instead, we relied on MQTT wildcards.
In MQTT, each topic is constructed from one or more levels, each separated by the delimiter /. Let’s take a look at this topic as an example, constructed of 3 levels.
While it is possible to simply subscribe to this topic, it is also possible to use MQTT wildcards to subscribe to it (only if the broker enables MQTT wildcards). There are two kinds of MQTT wildcards: single level wildcard (+), and multilevel wildcards (#).
Instead of subscribing to ALL devices unique topics, we simply used a single level wildcard (+) to subscribe to this topic.
This allowed us to receive ALL messages sent to ALL devices, and after a short while we accumulated hundreds of thousands of messages.
When examining the commands sent from the cloud, we noticed that they are essentially an OS command for the device to execute. That way, if the cloud wants the device to update its firmware for example, it constructs an OS command that fetches the firmware from the cloud and performs the system upgrade using it.
This means that in order to control devices through the cloud, Ruijie implemented an RCE-as-a-service, allowing them to execute OS commands on all cloud connected devices. We then tried seeing if we could send a command to a device, impersonating the cloud, and we were surprised to find out that we could!
This, combined with the list of ALL cloud connected devices serial numbers meant we now could execute OS commands on any cloud-connected device.
Open Sesame (CVE-2024-47146)
While executing code on all cloud-connected devices (~50,000) is fairly impressive, sometimes this is not an attacker’s desired outcome. Exploiting this vulnerability at scale could alert the vendor, who would issue a fix to the vulnerabilities needed for this exploit. In addition, many attackers would simply not gain anything by mass-exploiting tens of thousands of devices; this is only relevant in the case of an attacker attempting to build a botnet. Instead, most attackers would take a more targeted, stealthy approach.
To demonstrate this targeted attack scenario, we built an attack we called Open Sesame. It begins with identifying a target and then using the vulnerabilities we discovered above to execute code on vulnerable devices. To execute code on the target, all the attacker would need to know is the target’s serial number, and then use the vulnerabilities in Ruijie’s cloud to achieve RCE on the device.
The main functionality of Ruijie access points is to distribute Wi-Fi networks. This is why we see them in a versatile set of environments, such as a big office that needs Wi-Fi access in all of its corners, an airport that could span over a huge mass of land, or car garages that have Wi-Fi access, for example.
For the Open Sesame attack, an attacker in close proximity to a Wi-Fi network using Ruijie access points attacks the network and gains access to the internal network without prior knowledge of the Wi-Fi credentials.
To start this attack, the attacker would need to sniff raw Wi-Fi beacons. These beacons are constantly sent by all Wi-Fi providers to publish their Wi-Fi network and allow users to connect to it. In these beacons, devices can discover the name of the published Wi-Fi network, details about it (encryption, protocols etc), as well as information about the device publishing this network.
Using a wireless diagnostics tool and Wireshark, we were able to record these beacons.
When examining these messages, and looking in the vendor-specific data field (a field allowing the vendor to publish any data they choose), we discovered that the device actually publishes its serial number!
This meant that by simply being in close proximity to a Ruijie access point, and sniffing its raw beacon messages, an attacker could leak the device’s serial number. Then, using the vulnerabilities in Ruijie’s MQTT communication, an attacker could impersonate the cloud and send a message to the target device (identified by its SN the attacker leaked). This will result in the attacker supplying a malicious OS command for the device to execute, resulting in a reverse shell on the attacked Ruijie access point giving the attacker access to the device internal network.
Wrapping Up
Team82’s research on Ruijie’s infrastructure further exposes how vulnerable devices that are insecurely connected to, and managed through, the cloud can be. We demonstrated how we could use the cloud as an entry point toward ul
We decided to focus our research toward Ruijie’s cloud ecosystem, the Ruijie Reyee cloud platform, with the intention of using the cloud as our entry point into remote devices that are otherwise inaccessible.
We also developed an attack we call Open Sesame, whereby an attacker in close proximity to a Ruijie access point can sniff beacon messages from the device and leak the device serial number, which is used by Ruijie as a secret. We can then combine vulnerabilities we uncovered, especially in Ruijie’s implementation of the MQTT communication protocol to impersonate the cloud and send a message to the target device. An attacker could, for example, send a malicious OS command that the device would execute, creating a reverse shell on the access point and exposing access to the internal network of the device.