Hunting the Mongoose: Discovering 10 Vulnerabilities in the Mongoose Web Server Library

Hunting the Mongoose: Discovering 10 Vulnerabilities in the Mongoose Web Server Library

Embedded systems and IoT devices often operate with very limited processing power, memory, and storage. Standard libraries like OpenSSL, MbedTLS, or WolfSSL are robust and well-tested but can introduce too much overhead. This makes them impractical for environments like healthcare monitors or industrial control systems, where reliability and responsiveness are crucial to prevent breaches or disruptions.

A lightweight TLS implementation, such as the one offered by the Mongoose Web Server Library, is specifically designed to meet the needs of these devices, enabling secure communications without straining their limited resources.

Recognizing the critical role Mongoose plays in many devices, Nozomi Networks Labs conducted an in-depth analysis to improve the security posture of all products using this library for essential features like HTTPS servers, which are crucial for securing data transmissions and protecting sensitive information.

Our research uncovered 10 serious vulnerabilities in Mongoose's TLS implementation that could be exploited by sending a carefully crafted malicious TLS packet to the target device. Simply by sending a specially crafted TLS message, an attacker could cause a device that uses the Mongoose library to crash simply even if they only have basic network visibility to the target.

Given the serious risks involved, Cesanta, the vendor behind the Mongoose project, quickly developed Mongoose v7.15. This new release contains all the patches to address the issues we discovered.

In this blog post, we will walk you through the key highlights of our research on the Mongoose Web Server Library: we’ll explain how we uncovered these security flaws, discuss their impacts on IoT devices and explore what they mean for the broader security IoT ecosystem.

Research Scope

Mongoose is a lightweight, open-source networking library for embedded systems, managing protocols like HTTP, WebSocket, and TLS. The project has now reached 11k stars on GitHub and is deployed on hundreds of millions of devices worldwide. Due to its popularity, it is trusted by major companies such as Siemens, Schneider Electric, Bosch, and even NASA, which uses it aboard the International Space Station.

Cesanta, the company behind Mongoose, takes security very seriously:

  • The Mongoose repository uses a continuous integration system on GitHub that runs hundreds of unit tests on every commit, leveraging modern address sanitizer technologies to identify security vulnerabilities early.
  • Mongoose is integrated with Google's oss-fuzz, a continuous fuzzer that actively scans for potential vulnerabilities, ensuring the library is continuously monitored for emerging security issues.
  • Cesanta receives vulnerability reports from independent security organizations such as Cisco Talos, Microsoft Security Response Center, MITRE Corporation, Compass Security, and others.

Although Cesanta carefully handles all aspects of security, during our research, we identified that the built-in TLS protocol implementation was not integrated into the fuzz-testing pipeline. TLS (Transport Layer Security) is a protocol that plays a fundamental role in establishing secure HTTPS connections between clients and servers, ensuring data confidentiality and integrity. A vulnerability in the TLS library could have serious implications.

Due to the critical role that the TLS network protocol plays, we decided to investigate its security posture, hoping to uncover any hidden vulnerabilities, such as memory corruption or improper input handling, that could lower the safety of devices relying on this TLS implementation.

What Are the Impacts of These Vulnerabilities?

After analyzing the latest 7.14 version of Mongoose Web Server Library, we discovered 10 memory corruption vulnerabilities related to the TLS network protocol code that, if exploited, could lead to serious security risks for embedded and IoT devices.

Here are some of the high-level impacts of the vulnerabilities found:

  • Device crashes and instability: Many of the vulnerabilities (such as CVE-2024-42386) can be triggered by reading a malformed TLS packet sent by an attacker. This can cause the system to crash, leading to unexpected shutdowns or continuous reboots.
  • Denial of Service (DoS): By exploiting the CVE-2024-42384 vulnerability, an attacker could exploit the device’s inability to properly handle unexpected TLS packets and cause the device to become overloaded and unresponsive. In critical environments, such as hospitals or factories, this kind of attack can lead to serious safety issues.

These vulnerabilities are especially concerning for IoT environments, where devices often operate unattended, and a single compromised device could disrupt an entire network of connected systems. Addressing these vulnerabilities is essential to ensure reliable and secure operations in critical areas like healthcare, smart homes, and industrial automation.

Vulnerability List and Affected Versions

The following table list all the vulnerabilities Nozomi Networks Labs has found on the Mongoose Web Server v7.14 during this vulnerability research:

CVE IDCWECVSS v3.1 Base ScoreCVSS v3.1 Vector
CVE-2024-42383CWE-823: Use of Out-of-range Pointer Offset4.2CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:L/A:L
CVE-2024-42384CWE-190: Integer Overflow or Wraparound 7.5CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CVE-2024-42385CWE-140: Improper Neutralization of Delimiters4.0CVSS:3.1/AV:L/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:H
CVE-2024-42386CWE-823: Use of Out-of-range Pointer Offset8.2CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H
CVE-2024-42387CWE-823: Use of Out-of-range Pointer Offset5.3CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
CVE-2024-42388CWE-823: Use of Out-of-range Pointer Offset5.3CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
CVE-2024-42389CWE-823: Use of Out-of-range Pointer Offset5.3CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
CVE-2024-42390CWE-823: Use of Out-of-range Pointer Offset 4.3CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N
CVE-2024-42391CWE-823: Use of Out-of-range Pointer Offset 4.3CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N
CVE-2024-42392CWE-140: Improper Neutralization of Delimiters4.0CVSS:3.1/AV:L/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:H

Vulnerability Spotlight

Although the Mongoose library is integrated into Google's OSS-Fuzz project (you can find the C harness code here), we noticed that none of the TLS functions are tested by the existing harness. This observation prompted us to focus on the TLS attack surface, as it presents an interesting vector that could be exploited by an attacker with network access to the target.

Fuzzing a TLS stack implementation is notoriously challenging. TLS is inherently stateful, progressing through multiple stages like handshake, key exchange, and data transmission. To automatically generate valid test cases for testing such stateful protocols, the correct sequence and state of messages must be preserved to effectively evaluate different scenarios. Ensuring that the protocol is in a valid state at each step is complex, especially since different inputs can affect state transitions during fuzz testing.

SSL/TLS handshake overview. (Source: WolfSSL)

Given this complexity, we opted for a more straightforward approach. We began by analyzing the Mongoose TLS source code to understand where and how the first TLS packet is received by the client or server. We identified the key data structures involved and examined their internal states when the client or server processes the initial TLS packet. With this understanding, we coded a test case generator (C harness) that initializes these data structures with a valid internal state, provides a random TLS packet, and invokes the first TLS function that processes this input.

Our analysis revealed that both the client and server utilize the following data structures:

  • struct tls_data
  • struct mg_connection

These structures are initialized differently depending on whether they represent the client or server side of the communication. Both TLS peers use the mg_tls_handshake function to manage the entire TLS communication flow. This function reads incoming TLS network packets from the rtls field of the mg_connection structure and continues the TLS handshake based on the received packet.

With this information in mind, we crafted the following harness code:

C harness code (partial) to test mg_tls_handshake

The concept behind this code is straightforward and it can be summarized through the following steps:

  • Set up of a mock TLS client connection by initializing the tls_data and mg_connection structures with appropriate values to recreate a valid initial TLS state.
  • The c.rtls buffer is felt with the randomized TLS packet.
  • The mg_tls_handshake function is called so that the fuzzing input is processed just as it would be during a regular TLS handshake.

By focusing on the initial packet processing, we bypass the complexities of maintaining the full TLS state machine during fuzzing, allowing us to effectively test the TLS implementation for vulnerabilities that could be triggered by malformed or unexpected initial packets, without needing to simulate the entire protocol sequence.

Fuzzing mg_tls_ handshake with AFLplusplus.

After running the fuzzer for some time, a fault was detected by AddressSanitizer (ASAN). The crash provides the following valuable insights:

AddressSanitizer(ASAN) report

The report indicated a heap buffer overflow caused by a read operation in the gcm_update function. The invalid read occurred just beyond the allocated buffer, suggesting an off-by-one error or an incorrect calculation of buffer boundaries. To understand the cause of the crash, we focused on the mg_tls_recv_record function, where the initial decryption takes place. Here's a relevant snippet of the code:

Analyzing this function, we identified that it uses the rio->buf[3:4] bytes to compute the msgsz value:

msgsz =MG_LOAD_BE16(rio->buf + 3);

Then, when the client or the server uses AES GCM as decryption algorithm, they both execute the mg_aes_gcm_decrypt function subtracting 16 to the msgsz value:

mg_aes_gcm_decrypt(msg, msg, msgsz - 16, key, 16, nonce, sizeof(nonce));

But here's the catch: if msgsz is less than 16, subtracting 16 causes an integer underflow, resulting in a massive positive number due to wraparound. The consequences of this error are that the mg_aes_gcm_decrypt function is called with an input_length value that is bigger than the rio→buf TLS buffer. Then, when the gcm_update function iterates over all bytes, it triggers an out-of-bound read and the segmentation fault in the binary application occurs.

Segmentation fault occurring after receiving the malformed TLS packet.

After confirming the reason behind the crash, we decided to further investigate the malicious TLS packet that leads to this bug. As shown in the following evidence, none of the “length” fields of the TLS Client Hello packet has a value lower than 16, which is a necessary condition to trigger the integer underflow vulnerability that we previously discovered in the mg_tls_recv_record function.

Malformed TLS Client Hello packet discovered by the fuzzer.

However, a closer look to mg_tls_recv_record uncovers that the functions set the rio→buf TLS buffer not to the start of the TLS Client Hello packet but instead to its TLS ext field:

The mg_tls_recv_record function set the rio->buf to the TLS ext field.

By reading the fifth byte of this field, the function uses it to initialize the msgsz variable to 0x5. Due to this behavior, after subtracting 16 to this variable, the integer underflow occurs:

From msgsz to the integer underflow.
The application calls the mg_aes_gcm_decrypt function with an invalid input_length value.

Remediations

In this blog, we announced that disclosure of 10 memory corruption vulnerabilities that affect the TLS stack bult-in the Mongoose Web Server Library v7.14. Which, if exploited, could lead to serious security risks for embedded and IoT devices such as DoS. After receiving our findings, Cesanta promptly developed and released the Mongoose v7.15 library, which includes patches for all the vulnerabilities we identified during our research. Due to the severity impacts of these issues, we highly recommend all developers and organizations using the Mongoose library to upgrade to version 7.15 or later to ensure they are protected against these security issues.