← CVE-2023-24871 - intro & vulnerability description CVE-2023-24871 - LPE →

Having described the vulnerability in the previous post, here we’ll discuss how it can be used as an RCE vector. As mentioned previously, three different modules use the vulnerable function to parse advertisement data received from remote devices, so there’s a lot of ground to cover. Let’s get started.

contents


[1.0] prerequisites


For the vulnerability to be used as an RCE vector, advertisement data must come from the outside, i.e. it must be sent by a remote attacker and accepted by the system as valid, before finally reaching the vulnerable function in one of the affected modules. An attacker can easily send advertisement data of their liking from a remote device (i.e. a Windows computer) as long as they’re in reach, but the local system may reject such data due to certain limits.

First, the local system must be able to process extended advertisement data reports that are at least 514 bytes long, as data of shorter length cannot be made to trigger integer overflow. This is because each section must be at least 2 bytes long (containing the type and size fields), and there must be at least 257 sections to make the overflow happen. For this condition to be met, the local Bluetooth controller must support Bluetooth 5.0 and extended advertising, and the maximum length of advertising data supported by the controller must be at least 514. These constraints are controller/vendor-specific. The table below explains the conditions in detail, as well as which vendors are affected. I investigated four vendors: Intel, Qualcomm, Mediatek and Realtek, all of whom publish their drivers in the Microsoft Driver Catalogue.

Condition Description Comment Affected vendors
Bluetooth 5.0 The bluetooth controller used by Windows must support Bluetooth 5.0 - -
Extended Advertising The device driver must enable extended advertising. This feature is enabled during driver installation.

The driver specifies needs = BthLEExtendedAdvertisingOptIn.HW in its inf file to enable the feature.
Intel, Qualcomm, Mediatek
Maximum Advertisement Data Size Maximum advertisement data size must be greater or equal than 514. This value is read from the controller using the LE Read Maximum Advertisement Data Length HCI command.

bthport.sys stamps this value into PnP device properties using HCI_StampLocalRadioProperties.
Intel*, Qualcomm, Mediatek, Realtek

* Driver versions <= 22.120.0.2

* - For some reason, Intel reduced the maximum length of extended advertising data from 1650 to 160 in their driver update 22.130.x.x. I tested it on two separate bluetooth devices and for both of them the behaviour was the same. To this day the limit remains 160.

[2.0] reachability


Assuming the requirements necessary for the system to be vulnerable are met, the reachability of the vulnerable function depends on multiple other circumstances. These are:

  1. Which module is targeted.
  2. The type of the advertisement report used. Not all reports are parsed by all modules, so the attacker must choose a specific kind of advertisement report that they want to use.
  3. Whether the system is in active or passive scanning mode, i.e. whether the user or an application is currently scanning for bluetooth devices.
  4. Whether Microsoft Swift Pair is enabled.

Let’s better explain some of the conditions.

[2.1] advertisement scanning


The default behaviour of advertisement scanning on a Windows system using Bluetooth is different based on whether the system is actively searching for bluetooth devices or not:

  • In the active state, the system scans for all advertisement data coming from remote devices and forwards them to the system. This happens when the user tries to add a new bluetooth device from the settings, or if there’s a local application that requests for scanning to be active.
  • In the passive state, the system turns off active scanning of advertisement data coming from remote devices, accepting only reports from devices that are included in a local white list. The only devices on this list are LE devices that the system previously paired with and that remain in the known device list.
  • A special case here is Swift Pair, as it allows certain advertisements to reach the host even while it is in the passive state.

[2.2] Swift Pair


Swift Pair allows for the user to be notified when a nearby bluetooth device is ready to connect. Devices that want to be identified need to include a specific payload within their advertisement data. This payload is identified by the controller and forwarded to the host, which takes further action (ie shows a notification). The way this works in practice is that the host sends MSFT_HCI_Le_Monitor_Enable commands to the controller, which makes the controller monitor devices within a specific RSSI range that also satisfy a certain set of conditions. This process is performed in two steps:

1) If Swift Pair is enabled, the host will issue a MSFT_HCI_Le_Monitor_Enable command to make the controller monitor all devices within a specific RSSI range (observed values using the Intel Bluetooth Wireless controller are -65dBM to -55dBM) that also include the pattern 0x06 0x00 0x03 at offset 0 within their advertisement data. The host also tells the controller that the RSSI time threshold is 8 seconds, and that no RSSI sampling should be performed (ie only a single advertisement packet will be sent each time the device re-enters the RSSI range).

2) After the controller identifies such a device and forwards the advertisement data to the host, the host checks whether advertisement data is properly formatted. If so, it issues a second MSFT_HCI_Le_Monitor_Enable command - this one is specific to the identified device and lets the controller know it should forward advertisement data coming from this device as long as it’s within a specific RSSI range. RSSI sampling is set to 800ms in this case, which is the rate at which advertisement data packets will be forwarded from the controller to the host.

Assuming that advertisements do reach the host system, not all of them will reach all modules, and some of them will not reach the vulnerable function. Let’s see which conditions are necessary to reach the function in each module.

[2.3] Modules


Let’s get to know the affected modules. We’ll refer to them by their short names:

  • bthport refers to bthport.sys, the Windows Bluetooth port driver. It’s at the very bottom of the stack and its purpose is very general - it implements quite a few protocol layers, such as HCI, L2CAP and SDP, while simultaneously being a “classic” driver with IO handlers that usermode components can use to issue bluetooth commands.
  • bthserv referes to Bluetooth Support Service, an automated service that runs on Windows installations that support and enable Bluetooth. The service is run as the LOCAL SERVICE user, and handles logic relating to user-mode bluetooth components that are exposed to outside applications via WinRT APIs.
  • dafbth refers to dafBth.dll, a module which is used by the Device Association Service, an automated service that is used to classify and sort devices recognized by the system.

[2.3.a] bthport

bthport processes only specific advertisement data reports using the vulnerable function. The conditions are located in BthLE_ProcessAdvertisementEvent:

  • Reports marked as “Scannable”, “Connectable” or “Scan Response” will be processed. However, some of these reports have further limitations on how much data they can transfer at once:
    • Connectable extended advertising reports can only contain 251 bytes of advertisement data and cannot be used to trigger the vulnerability.
    • Scannable extended advertising reports must contain no advertisement data and cannot be used to trigger the vulnerability.
    • Scan Response extended advertising reports can contain an arbitrary amount of advertising data and can be used to trigger the vulnerability.
    • All legacy advertising reports can only contain 31 bytes of advertisement data and cannot be used to trigger the vulnerability.
  • All reports coming from a device address that can be matched to a registered LE Client will be processed.
    • A registered LE client is a device that the system is connected to in one way or another. Since this requires authentication against the device (usually) and more complex user interaction, we’ll forget about this condition.
  • All reports if NonConnectableDib registry value is set to “1” within the PnP device properties registry key for the currently used Bluetooth device.
    • The four investigated vendors currently don’t enable this feature.

[2.3.b] bthserv

In bthserv, the vulnerable function is located in Microsoft.Bluetooth.Service.dll. Advertisement data is processed by a GapAdvertisementMonitorImpl object, which doesn’t filter advertisement reports and will forward all of them to the vulnerable function. As such, reachability depends on the existence of these objects. GapAdvertisementMonitorImpl is commonly created in three different cases:

  • If Swift Pair is enabled, Bluetooth User Support service will register a monitor object to look for advertisement data of devices that want to connect using Swift Pair.
  • If there are any Bluetooth LE devices paired with the system, a monitor object will be registered to look for advertisements coming from these devices.
  • A local unprivileged application can request to watch for advertisements using the Bluetooth API, which will create a monitor object.

[2.3.c] dafbth

The vulnerable function in dafbth, as used by the Device Association service, is reachable from CBthProviderAssociation::StartInitOobAssociation via BthParseOOBBlob. This code is executed when bthserv issues a call to DafCreateAssociationContextFromOobBlob, which happens in two cases:

  • When a prepaired device is found.
  • When a new device is connected to the system.

Triggering the vulnerablity in this module would require the attacker to either spoof a prepaired device (unlikely, and systems with prepaired devices are rare) or get the user to connect via Bluetooth to a remote device the attacker controls. Additionally, the crafted advertisement data would have already been processed by bthserv through its own vulnerable code path. Given these conditions, exploiting the vulnerability in dafbth is quite unlikely and this module will not be in focus in the remainder of the report.

[3.0] Attack vectors and impact


Putting everything together, we get the true impact of the vulnerability: An unauthenticated physically-adjacent attacker can achieve remote code execution in the Windows kernel or in the context of the NT AUTHORITY\LOCAL SERVICE user, depending on which module is exploited. The attack vector includes data transferred over Bluetooth to a vulnerable device. Setting up a necessary payload doesn’t require any controller programming and can be done relatively easily using popular Bluetooth host APIs. Targeted attacks can be accomplished with directed advertisements to the MAC address advertised by the target system.

Triggering the vulnerability by leveraging Swift Pair requires the remote device to be within a monitored RSSI range. Even though RSSI is proximity-based and the parameters set by Windows indicate an RSSI range that translates to distances lower than 1 meter for most Bluetooth devices, an attacker could use a device with significantly higher signal strength, reaching required RSSI values at longer distances. Furthermore, triggering the vulnerability remotely requires the attacker to be able to reach the target system via Bluetooth, but two way communication is not required. This means that the vulnerability can be triggered over long distances by using remote devices with significant signal strength, and doesn’t depend on the signal strength of the local controller.

[3.1] Attack scenarios


We have a bunch of different conditions that need to be satisfied to trigger the vulnerability. We also have two modules that could possibly be abused. To consolidate this information into a more natural format, I created a scenario table, which enumerates four different scenarios that affected whether and how the different components are vulnerable. The table below assesses whether bthserv and bthport are directly vulnerable, i.e. with no prior execution on the system.

Note that the last column denotes whether the scenario allows the attacker to repeatedly attempt to exploit the vulnerability even if failed attempts crash bthserv. The service is setup to immediately restart itself after crashing, but the advertisement monitor needed to reach the vulnerable function won’t always be re-registered in the new process.

Scenario # System actively scanning System has a paired BLE device Swift Pair Enabled bthport vulnerable? bthserv vulnerable? Attack complexity User interaction Repeatable in bthserv?
1 Yes No No Yes

Crafted SCAN_RSP packets will be forwarded from the host to the controller and processed by bthport.
No

There are no advertisement monitor objects registered in bthserv, the vulnerable function will not be called.
Low

The attacker has to send specific data over Bluetooth.
Circumstantial

The user must actively start scanning for nearby bluetooth devices or run an application that turns on Bluetooth scanning via API calls. No interaction with the attacker is required.
N/A
2 Yes Yes No Yes

Crafted SCAN_RSP packets will be forwarded from the host to the controller and processed by bthport.
Yes

An advertisement monitor is registered to watch for devices that are paired with the system.
Low

The attacker has to send specific data over Bluetooth.
Circumstantial

The user must actively start scanning for nearby bluetooth devices or run an application that turns on Bluetooth scanning via API calls. No interaction with the attacker is required.
Yes

The service restarts after crashing and immediately registers an advertisement monitor again.
3 No Yes No Yes

bthport will process advertisement reports coming from addresses of paired BLE devices, as these are registered as LE clients.
Yes

An advertisement monitor is registered to watch for devices that are paired with the system.
High

The attacker has to spoof the address of a paired BLE device and send specific data over Bluetooth.**
None Yes

The service restarts after crashing and immediately registers an advertisement monitor again.
4 No No Yes No

The system is not actively scanning, SCAN_RSP packets will be discarded by the controller and won’t reach the host.
Yes

Bluetooth User Support service registers an advertisement monitor to watch for devices in proximity that support Swift Pair.
Low

The attacker has to send specific data over Bluetooth by using a device whose signal strength is within the Swift Pair monitoring range.
None No

After bthserv restarts, Bluetooth User Support Service does not re-register an advertisement monitor.***

** The attacker could spoof the address of the device by brute force or by sniffing radio data. This step is required in order for the advertising data to be forwarded to the host, as passive scanning is setup to allow only advertisements from whitelisted devices to reach the host.

*** This is probably a bug, as it effectively means that in the event of bthserv crashing, Swift Pair will cease to function until the system is rebooted or Bluetooth User Support service is restarted.


[4.0] poc

I published the PoC on github. It can be used to trigger the vulnerability in all four situations, all you need is a programmable bluetooth device to run the code on. Unfortunately, I didn’t manage to exploit the vulnerability, though I didn’t try too hard. The most attractive option is the zero-click situation via SwiftPair, but the interaction that a remote device can have with bthserv is very limited without any authentication, meaning that defeating ASLR, setting up the heap etc. would be pretty hard. It’s a shame since vulnerability primitives are pretty nice and can be used for an LPE exploit, as we’ll see in the next post.

Below you can find a demonstration video for each scenario. These are the same videos I sent to Microsoft, and they show the PoC in action on one of the old W11 insider builds. The quality is a bit shit but re-recording them would require setting everything up again and I didn’t want to bother.

Scenario 1


Scenario 2


Scenario 3


Scenario 4


← CVE-2023-24871 - intro & vulnerability description CVE-2023-24871 - LPE →