Team82 Logo Claroty
Return to Team82 Research

The Insecure IoT Cloud Strikes Again: RCE on Ruijie Cloud-Connected Devices

/

Executive Summary

  • Team82 has researched devices manufactured by Ruijie Networks and discovered 10 vulnerabilities in its Reyee cloud management platform

  • These vulnerabilities affect both the Reyee platform, as well as Reyee OS network devices

  • 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

  • In addition, Team82 has devised an attack called Open Sesame, in which an attacker can pinpoint exploit a device in close physical proximity through the cloud, executing arbitrary code on it and gaining access to its internal network

  • Ruijie has addressed all vulnerabilities in the cloud, and no action is required by users.

  • We would like to acknowledge Ruijie Networks and CISA for their cooperation in addressing these issues, which enhances the protection of the Reyee OS platform.

Introduction

Our 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 we call Open Sesame. Here, an attacker in close physical proximity to a Ruijie Reyee OS access point could exploit and leak identifiers over-the-air, and attack the device through the Ruijie cloud platform, giving them remote code execution on the device and access to its internal network.

Watch this demo of the Open Sesame attack

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. 

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 $1.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.

An airport with an access point made by Ruijie - used for WiFi network access.

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.

A diagram showcasing the network architecture of the attack we wish to exploit an attacker executing code on a Ruijie access point sitting behind a FW/NAT.

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 pairing process whereby a device connects back to the cloud on boot and identifies itself using its serial number.

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. 

The Ruijie web interface where users may claim their devices upon registering them.

Device-to-Cloud Communication

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

The Ruijie firmware download page.

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.

The entropy of the Ruijie firmware file demonstrates even distribution.

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.

The decryption binary on Ruijie devices.

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.

Magic header for encrypted Ruijie firmware.

Knowing we are looking at the correct component we started a simple analysis of the binary encryption scheme. Finding the decryption routing and understanding essentially how it works was quick.

It was a propriatery implementation of a simple symmetric encryption scheme based on xoring the content with a predetermined secret key inside the executable. This brief overview of the executable gave us the sense it will be quite easy to execute this binary with our encrypted firmware image and by doing so decrypting its content.

So 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.

Building a minimalistic filesystem for the Ruijie decryption binary.

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.

Decrypting the device firmware.

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.

The Ruijie firmware structure.

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.

The main cloud binary used by Ruijie devices

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.

Reading strings from Ruijie main cloud binary, showcasing that they use mosquitto as their MQTT library.

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:

  1. Identifying Ruijie’s MQTT broker

  2. 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:

The configuration of Ruijie MQTT.

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 in the following routine:

The routine handling MQTT password generation.

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.

How Ruijie devices read their serial numbers.

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.

Unsuspecting users on Youtube, leaking their device’s serial number (which translates to the device credentials).

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.

A script connecting to Ruijie’s 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:

  1. cloud/sync: Over this topic, devices send keepalive messages and status reports.

  2. cloud/config_change: Over this topic, devices notify the cloud about config changes performed on them.

  3. cloud/event: Over this topic, devices send event notifications to the cloud, like a reboot event, firmware upgrade etc.

  4. 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.

Ruijie topic construction.

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!

An MQTT message sent by a device to the Ruijie MQTT broker - received by our client.

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!

A sample from a list of tens of thousands of Ruijie device 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.

The state tree we managed to achieve, allowing us to perform a denial of service attack on all Ruijie cloud connected devices.

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 analyzed 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 :

first/second/third

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 (#). Here is how these wildcards could be used to subscribe to this topic:

first_level/+/third

first_level/#

With this knowledge, instead of subscribing to ALL devices unique topics, we simply used a single level wildcard (+) to subscribe to this topic: 

cloud/+

This allowed us to receive ALL messages sent to ALL devices, and after a short while we accumulated hundreds of thousands of messages.

Example of messages we got from the cloud once we subscribed to all devices topics.

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.

A formatted command sent from the cloud to a device, containing an OS command for the device to execute.

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!

A PoC publishing a message to a device’s topic, and receiving the message, showcasing the message was successfully sent.

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.

An attacker in an airport trying to attack an adjacent Ruijie access point.

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.

Wi-Fi beacons sent by a Ruijie access point, publishing its Wi-Fi SSID.

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.

The attacker executing code on the attacked Ruijie access point.

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.   

Stay in the know Get the Team82 Newsletter
Related Vulnerability Disclosures
Claroty
LinkedIn Twitter YouTube Facebook