This blog post presents our fuzzer for the Bluetooth Low Energy GATT layer and the related vulnerabilities found with it.

Introduction

Bluetooth Low Energy (BLE) is a widely adopted wireless communication technology used by billions of devices in various applications. These applications range from IoT domain to more sensitive devices such as medical ones.
BLE has been subject to a lot of research so far [1, 2, 3], but only a few of them targeted specification corner cases which require high-level manipulation of the GATT layer.

Based on that reason, we decided to build a fuzzer based on attack scenarios defined after conducting an in-depth study of the BLE specification. Our work resulted in the discovery of non-conformities, bugs, and vulnerabilities in various BLE stacks.

This R&D work was carried out during Baptiste Boyer's internship at Quarkslab.

BLE analysis

The BLE protocol is built upon multiple layers that extend from the radio layer to the application layer as described below:

BLE Protocol Stack.

BLE Stack


Our study focuses on the Attribute Protocol (ATT) layer and on the Generic Attribute Protocol (GATT) layer. However, it is also important to define the two key components of the BLE framework that are the Host and the Controller.

The Host and Controller represent distinct entities with specific roles in the communication process. The Host is typically associated with the device’s primary processing unit, such as a computer or smartphone. It oversees higher layers of the BLE protocol stack, managing connections, configuring parameters, and handling application-specific communication needs. In contrast, the Controller operates at a lower layer, responsible for radio frequency communication aspects. Implemented in specialized hardware, like a Bluetooth chip, the Controller executes tasks such as frequency hopping, modulation, and power control, ensuring reliable and efficient radio communication. To be able to communicate together, they use the Host Controller Interface (HCI).

ATT Layer

The Attribute Protocol (ATT) defines two distinct roles: a server and a client. The server is responsible for storing and managing attributes, while the client accesses and manipulates these attributes. In this context, an attribute is a data representation format composed of four fields.

The Attribute data structure has the following format:

Attribute field Size (bytes) Description
Handle 2 A unique identifier assigned to each attribute, allowing devices to reference and interact with them.
UUID 2 or 16 An identifier that uniquely identifies a specific attribute type, defining its purpose and characteristics.
Value Variable length The actual data associated with an attribute, representing the information communicated between devices.
Permissions Implementation specific Access rights and restrictions governing how and attribute can be read, written, or otherwise interacted with by devices, ensuring security and control over the data exchange.

The ATT Protocol outlines methods for both reading and writing attributes. These methods involve ATT Protocol Data Unit (PDU) for communication. In the context of the ATT protocol, a PDU represents the packet that is exchanged with the lower layer – specifically, the L2CAP layer. This packet is then encapsulated for transmission over the physical link or sent to the upper layers.

Attribute PDUs have the following format:

Name Size (bytes) Description
Attribute Opcode 1 The attribute PDU operation code.
bit 7: Authentication Signature Flag.
bit 6: Command Flag.
bits 5-0: Method.
Attribute Parameters 0 to (ATT_MTU - X) The attribute PDU parameters.
X = 1 if Authentication Signature Flag of the Attribute code is 0.
X = 13 if Authentication Signature Flag of the Attribute code is 1.
Authentication Signature 0 or 12 Optional authentication signature for the Attribute Opcode and Attribute Parameters.

Let’s elaborate on the behavior of the ATT PDU called Prepare Write Request, as most of our findings are associated with this ATT PDU.

The Prepare Write Request ATT PDU is vital when dealing with the need to write a long Attribute value, i.e., an attribute value where its size exceeds (ATT_MTU - 1). The default Maximum Transmission Unit (MTU) in BLE communications is 23 bytes. This ATT PDU is used to request the server to prepare the write of a value for a specified attribute. The server responds with a Prepare Write Response to confirm the correct reception of the value. Multiple Prepare Write Request ATT PDUs may be sent to transmit the complete Attribute value. Once all the ATT PDUs have been transmitted, the client sends an Execute Write Request to instruct the server to write the value.

The format of the Prepare Write Request is as follows:

Parameter Size (bytes) Description
Attribute Opcode 1 0x16 = ATT_PREPARE_WRITE_REQ PDU.
Attribute Handle 2 The handle of the attribute to be written.
Attribute Offset 2 The offset of the first byte to be written.
Part Attribute Value 0 to (ATT_MTU-5) The value of the attribute to be written.

GATT Layer

The Generic Attribute Profile (GATT) establishes a service framework built upon the ATT Protocol. This framework defines procedures and formats for services and their characteristics are defined. These procedures encompass various operations such as discovering, reading, writing characteristics but also notifying and indicating any characteristic value modification. Additionally, GATT outlines procedures for configuring the broadcast of characteristics. It also defines some standard profiles with associated services and characteristics.

The GATT Profile establishes the format for exchanging profile data, defining fundamental elements such as services and characteristics within the structure. These elements are encapsulated by Attributes, which serve as containers for carrying profile data in the ATT Protocol.

Profile Hierarchy.

GATT Profile Hierarchy


Attack scenarios

After an in-depth study of the specification, 9 attack scenarios were defined. The main goal of this study was to pinpoint corner cases and inaccuracies within the specification, providing a foundation for the development of precise attack scenarios.

The description of the scenarios is provided in the related paper.

Fuzzer

The attack scenarios were implemented as fuzzing scripts in Python using the WHAD framework.

We opted for WHAD as our chosen framework for its specific capabilities in the BLE context. This framework equips us with all the essential tools for testing the GATT layer, including transparent PDUs logging and its own BLE stack implementation. It offers simple methods to create and send BLE packets, encompassing the entire spectrum of ATT possibilities. Additionally, it facilitates the seamless setup of a GATT server and enables straightforward modification of its behavior.

The fuzzer architecture was designed with certain key choices in mind. One notable decision involved the type of connection established during a fuzzing session. Instead of initiating a new connection for each test case, we opted for a single connection for the entire fuzzing session. This choice was driven by the belief that retaining previous states of the stack could potentially aid in triggering and identifying bugs.

We opted for a randomized approach to populate the ATT PDUs. An example illustrating the Prepare Write Request ATT PDU mentioned earlier is provided below. Additionally, it is worth noting that each fuzzing session focused solely on testing a single scenario.

def mutate_fill_payload(att_proc, gatt_handle):
    """
    Fills and returns the ATT primitive
    """

    match att_proc:
    ...
     case scapy.layers.bluetooth.ATT_Prepare_Write_Request:

        _gatt_handle = random.choice(gatt_handle)
        _offset = random.randint(0,65535)
        n = random.randint(0,80)
        _data = random.randbytes(n)

        return ATT_Prepare_Write_Request(gatt_handle = _gatt_handle, 
                                         offset = _offset,
                                         data = _data) , 5 + n

Several parameters are set through the CLI interface, the help option displays the following content:

CLI help.

CLI help output


The tool implementing the scripts scenario can be found on Quarkslab's GitHub.

Results

Only the vulnerabilities are discussed in this section. The description of the non-conformities and bugs is provided in the related paper.

Espressif GATT server example

This vulnerability is associated with the Bluedroid stack provided in the ESP-IDF framework. More specifically, it is related to the GATT server example provided for Espressif devices, intended for using Bluedroid. This vulnerability exposes a risk of heap overflow.

We uncovered this vulnerability during the code review of the Bluedroid stack. Building on our prior discoveries of bugs, our aim was to assess the impact on user applications. Upon scrutinizing the provided GATT server example, we finally identified this Out-of-Bounds write issue.

Their initial misguided decision involves allowing the user to verify the conformity of parameters provided in the Prepare Write Request ATT PDU by default.

The root cause of the vulnerability was located in the example_writ_event_env() function during the copy of a received Prepare Write Request’s value into the allocated buffer prepare_buf as we can see in the code below:

memcpy(prepare_write_env->prepare_buf + param->write.offset,
       param->write.value,
       param->write.len);

An attacker controls both the offset and the value and is able to write outside of the allocated buffer. A check on the offset is actually done but only when the allocated buffer has already been allocated, and therefore this check is not performed for the first received Prepare Write Request.

void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){
    [...]
    if (prepare_write_env->prepare_buf == NULL) {
        prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE*sizeof(uint8_t));
        prepare_write_env->prepare_len = 0;
        if (prepare_write_env->prepare_buf == NULL) {
            ESP_LOGE(GATTS_TAG, "Gatt_server prep no mem\n");
            status = ESP_GATT_NO_RESOURCES;
        }
    } else {
        if(param->write.offset > PREPARE_BUF_MAX_SIZE) {
            status = ESP_GATT_INVALID_OFFSET;
        } else if ((param->write.offset + param->write.len) > PREPARE_BUF_MAX_SIZE) {
            status = ESP_GATT_INVALID_ATTR_LEN;
        }
    }

Unfortunately, Espressif did not categorize this as a vulnerability within their bounty program, treating it solely as a bug despite its clear manifestation as a heap overflow issue. However, following our report, this vulnerability has been fixed in a timely manner by Espressif without any communication about it, affecting 7 of their code examples. We are curious to know about the number of applications that relied on these code examples and remain susceptible to our discovery.

Espressif's response: "Regarding the issue with the example memcopy, this problematic code segment is not present in the host and controller codes. It is solely included in the Example to demonstrate how the ESP API is used. Typically, customer code is autonomously developed based on the API, and the impact of this issue on customers is minor, lacking any substantial consequences."

CVE-2024-24746

Denial of Service of NimBLE Bluetooth stack.

During the analysis of the log files from our fuzzing campaign, we observed instances where the device has terminated the connection by itself. Upon further investigation, we identified a recurring pattern associated with disconnections: transactions involving Prepare Write Requests that were not completed within a 30-second timeframe.

Indeed, the BLE specification stipulates that "A transaction not completed within 30 seconds shall time out. Such a transaction shall be considered to have failed, and the local higher layers shall be informed of this failure." [Spec Vol.3 Part.F 3.3.3]. NimBLE implements this feature with the BLE_ATT_SVR_QUEUE_WRITE_TMO timer.

When the initiating device sends a Prepare Write Request to the BLE peripheral, the NimBLE stack starts a timer to remove later the pending write operations if no Execute Write Request or Prepare Write Request is received within the specified time frame. If the initiating device disconnects from the peripheral just before the timeout is reached, then the peripheral will be stuck in an infinite loop and therefore will not advertise anymore even if the current connection has been terminated. This lack of advertising prevents any new connections, resulting in the device remaining unconnectable until it is reset.

The following schema shows an overview of what is happening:

Denial of Service on NimBLE GATT server.

NimBLE Denial of Service


Sony headsets

Denial of Service of Sony headsets.

We wanted to reproduce CVE-2024-24746 on real-world devices. We opted for commonly available audio devices, including the Sony WH-1000XM4, WF-1000XM4 and WH-1000XM5, as some colleagues had these models on hand. We successfully managed to crash all these devices by attacking their exposed BLE GATT servers in the same manner as we did with the NimBLE GATT server.

In the following, we will detail the Denial of Service attack process only for the Sony WH-1000XM4. Similar processes have been used for the WF-1000XM4 and WH-1000XM5.

By default when used with Bluetooth Classic to listen to music, this device like many Bluetooth audio devices exposes a BLE GATT server typically labeled as LE_WH-1000XM4, featuring a range of characteristics with various permissions. Our goal was to find an enabled Prepare Write Request characteristic. We discovered the service with the 16-bit UUID FE2C, known as the Fast Pair Service, which is present on many Bluetooth audio devices. This service has characteristics with write permissions.

We noticed that following a Prepare Write Request with an Execute Write Request caused the headset to disconnect by itself. At this point, it became evident that we encountered a scenario similar to the NimBLE DoS vulnerability. After sending a single random request before each connection drop, we identified an ATT PDU that consistently caused the device to crash after few try, a Find By Type Value Request with specific parameters.

The following schema shows an overview of what is happening:

Denial of Service on Sony WH_1000XM4.

Sony WH-1000XM4 Denial of Service


A Proof of Concept for this vulnerability is provided on Quarkslab's GitHub.

Conclusion

In this blog post, we conducted an in-depth analysis of the BLE specification, leading us to elaborate and implement attack scenarios using the WHAD framework. Our research uncovered several non-conformities, bugs, and vulnerabilities across multiple BLE stacks, highlighting the need for more attention and improvement in these layers to enhance overall security.

More detail can be found in the related paper.

Disclosure timeline

Espressif

  • 2023-12-05 Quarkslab sent report via email.
  • 2023-12-06 Espressif acknowledged the report and asked details to be resent in plaintext.
  • 2023-12-06 Quarkslab sent the report in plaintext.
  • 2023-12-07 Espressif confirmed they received the report.
  • 2023-12-21 Espressif said it could reproduce the two bugs (DoS, OOB write) but they do not consider them vulnerabilities.
  • 2023-12-23 Quarkslab acknowledged the last email and asked if Espressif could elaborate on the criteria used to triage the bugs.
  • 2023-12-29 Espressif replied that impact of the first bug is just disconnection of the attached device, since it does not impact normal use nor leak user data it cannot be considered a vulnerability. The second bug (OOB write) is not present in Host or Controller code, it only affects example code and customers typically develop autonomously based on the API, so the impact is minimal.

CVE-2024-24746

  • 2024-01-19 Quarkslab sent report via email to Security Team.
  • 2024-01-21 Apache MyNewt PMC acknowledged the report.
  • 2024-01-25 Apache developer confirmed the report and said they are working on a fix.
  • 2024-02-06 Quarkslab acknowledged the last email.
  • 2024-02-07 Apache MyNewt PMC said it had sent a proposed patch for testing a week ago
  • 2024-02-13 Apache asked if Quarkslab could test the patch.
  • 2024-02-14 Quarsklab replied that they tested the patch and could not reproduce the bug.
  • 2024-02-14 Apache MyNewt PMC published a fix.
  • 2024-04-05 Apache MyNewt PMC assigned CVE ID CVE-2024-24746 to the vulnerability.
  • 2024-04-05 Quarkslab asked Apache to acknowledge Baptiste Boyer as reporter.
  • 2024-10-25 Blog post is published.

Sony headsets

  • 2024-07-22 Quarkslab sent report via email to Sony.
  • 2024-07-23 Sony acknowledged the report.
  • 2024-07-31 Sony asked for more details to be able to reproduce the Denial of Service.
  • 2024-08-05 Quarkslab sent more details and Proof of Concept program.
  • 2024-08-06 Sony said it had reproduced the bug in one model but now on the other two and asked to Quarkslab to try with auto power off turned off
  • 2024-08-06 Quarkslab re-sent the PoC program, since Sony received it mangled in the prior email.
  • 2024-08-12 Quarkslab confirmed the bug persists with auto power off disabled and sent a WHAD-based fuzzer to Sony.
  • 2024-08-19 Sony they were working on identifying the root cause of the bug, asked where the research would be presented.
  • 2024-09-09 Sony said it is working on fixes and asked how to acknowledge the report. Also asked where will the research be presented.
  • 2024-09-10 Quarkslab replied asked to acknowledge Baptiste Boyer, and said he would present at the hardwear.io conference.
  • 2024-09-12 Sony asked the day of the presentation to coordinate publication on their web site, also requested the slides.
  • 2024-09-13 Quarkslab replied that it will provide the slides as a courtesy when they are ready.
  • 2024-10-02 Sony published a fix for WH-1000XM5.
  • 2024-10-17 Sony published fixes for WH-1000XM4 and WF-1000XM4.
  • 2024-10-21 Quarkslab sent the slides of the hardwear.io talk to Sony.
  • 2024-10-25 Sony acknowledged Quarkslab for the vulnerabilities finding.
  • 2024-10-25 Blog post is published.

If you would like to learn more about our security audits and explore how we can help you, get in touch with us!