BLESA: GATT Client Vulnerabilities
For Bluetooth Low Energy (BLE) connections, most application make use of the Generic Attribute Profile (GATT) profile. Access to data on the GATT Server can require authentication on a fine-granular level. However, this security is only enforced by the GATT Server. If an attacker uses the Bluetooth address of a previously paired device, it can configure its GATT Server with no authentication requirements and interact with the fooled GATT Client. Similarly, if the attacker is present during the first connection, the GATT Client may interact with the attacker without any form of pairing. These issues were analyzed in the BLESA paper. The issues are not limited to a particular implementation, they are based on an incomplete Bluetooth specification.
A device is only vulnerable if it uses a GATT Client and the data exchanged with other devices is sensitive.
Communicating with an unauthenticated attacker on reconnect
To address the issue of communicating with an unauthenticated attacker on reconnect, the authors propose to use Proactive versus Reactive Authentication. With Reactive Authentication, the GATT Client (or the application) requests a higher security level when the remote GATT Server returns an “insufficient encryption/authentication” error. With Proactive Authentication, a higher security level is requested immediately after the connection is established if bonding information is available.
We have implemented Proactive Authentication in BTstack v1.2.1. To enable it, add in
The behavior with Proactive Authentication differs between Central and Peripheral role. In Central role, after a connection to a bonded device is created, the device will start re-encryption of the connection.
In Peripheral role, after a bonded device has connected, the device will send a Security Request. The Security Request triggers authentication by the remote device, which will start re-encryption. If the re-encryption fails, it is reported to the application. The application is free to either delete the bonding information and start pairing, or, to discard the connection.
To allow the application to observe the security procedure, the Security Manager emits the following events:
SM_EVENT_PAIRING_COMPLETE: with status.
SM_EVENT_REENCRYPTION_STARTED: if encryption is requested and bonding information is available.
SM_EVENT_REENCRYPTION_COMPLETE: if remote does not use bonding information, status is set to
Please note: On connect to a bonded device with Proactive Authentication enabled, a
SM_EVENT_REENCRYPTION_STARTED is expected. This also happens if the device is in Peripheral role and the Central responds with a Pairing Request instead of starting the encryption. This indicates that the remote has lost its bonding information or might not have it as an attacker.
Communicating with an unauthenticated attacker on first connect
To address the issue of communicating with an unauthenticated attacker on first connect, we added the
gatt_client_set_required_security_level function, let’s call it Mandatory Authentication. When called with security level greater than zero, the GATT Client will post-pone any request until the security level was raised, then it will trigger pairing, re-encryption, or it will send a Security Request as needed. If re-encryption fails, the bonding information must be deleted before communication with this device becomes possible again.
If you’re connecting to a device under your control and you know that authentication is mandatory, please use
gatt_client_set_required_security_level to trigger pairing before any GATT Client request is sent. If you don’t control the remote device, but want to prevent the spoofing attacks described in the BLESA paper, please add
ENABLE_LE_PROACTIVE_AUTHENTICATION to your
In both cases, please keep in mind that you probably need to handle the case, where a legitimate device looses its bonding information. In this case, it is recommended to inform the user on the failed re-encryption. If the user agrees, the application can delete the bonding information and trigger pairing again. See
example/sm_pairing_central.c for reference.