Skip to content

Bluetooth characteristic LESC security requirement not enforced without additional flags

High
ceolin published GHSA-p6f3-f63q-5mc2 Feb 19, 2024

Package

No package listed

Affected versions

<= 3.5.0

Patched versions

None

Description

Summary

The documentation specifies that the BT_GATT_PERM_READ_LESC and BT_GATT_PERM_WRITE_LESC defines for a Bluetooth characteristic: Attribute read/write permission with LE Secure Connection encryption. If set, requires that LE Secure Connections is used for read/write access, however this is only true when it is combined with other permissions, namely BT_GATT_PERM_READ_ENCRYPT/BT_GATT_PERM_READ_AUTHEN (for read) or BT_GATT_PERM_WRITE_ENCRYPT/BT_GATT_PERM_WRITE_AUTHEN (for write), if these additional permissions are not set (even in secure connections only mode) then the stack does not perform any permission checks on these characteristics and they can be freely written/read.

Details

File subsys/bluetooth/host/gatt.c lines 3072 onwards has:

uint8_t bt_gatt_check_perm(struct bt_conn *conn, const struct bt_gatt_attr *attr,
                        uint16_t mask)
{
        if ((mask & BT_GATT_PERM_READ) &&
            (!(attr->perm & BT_GATT_PERM_READ_MASK) || !attr->read)) {
                return BT_ATT_ERR_READ_NOT_PERMITTED;
        }

        if ((mask & BT_GATT_PERM_WRITE) &&
            (!(attr->perm & BT_GATT_PERM_WRITE_MASK) || !attr->write)) {
                return BT_ATT_ERR_WRITE_NOT_PERMITTED;
        }

        if (IS_ENABLED(CONFIG_BT_CONN_DISABLE_SECURITY)) {
                return 0;
        }

        mask &= attr->perm;

        /*
         * Core Specification 5.4 Vol. 3 Part C 10.3.1
         *
         * If neither an LTK nor an STK is available, the service
         * request shall be rejected with the error code
         *  ^`^|Insufficient Authentication ^`^}.
         * Note: When the link is not encrypted, the error code
         *  ^`^|Insufficient Authentication ^`^} does not indicate that
         *  MITM protection is required.
         *
         * If an LTK or an STK is available and encryption is
         * required (LE security mode 1) but encryption is not
         * enabled, the service request shall be rejected with
         * the error code  ^`^|Insufficient Encryption ^`^}.
         */

        if (mask & (BT_GATT_PERM_ENCRYPT_MASK | BT_GATT_PERM_AUTHEN_MASK)) {
#if defined(CONFIG_BT_SMP)
                if (!conn->encrypt) {
                        if (bt_conn_ltk_present(conn)) {
                                return BT_ATT_ERR_INSUFFICIENT_ENCRYPTION;
                        } else {
                                return BT_ATT_ERR_AUTHENTICATION;
                        }
                }

                if (mask & BT_GATT_PERM_AUTHEN_MASK) {
                        if (bt_conn_get_security(conn) < BT_SECURITY_L3) {
                                return BT_ATT_ERR_AUTHENTICATION;
                        }
                }

                if (mask & BT_GATT_PERM_LESC_MASK) {
                        const struct bt_keys *keys = conn->le.keys;

                        if (!keys || (keys->flags & BT_KEYS_SC) == 0) {
                                return BT_ATT_ERR_AUTHENTICATION;
                        }
                }

It is if (mask & (BT_GATT_PERM_ENCRYPT_MASK | BT_GATT_PERM_AUTHEN_MASK)) { that causes this issue

PoC

static ssize_t read_u8(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
                       uint16_t len, uint16_t offset)
{
        const uint8_t *value = attr->user_data;
        printk("security level: %d\n", bt_conn_get_security(conn));
        return bt_gatt_attr_read(conn, attr, buf, len, offset, &value, sizeof(value));
}

static ssize_t write_u8(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf,
                        uint16_t len, uint16_t offset, uint8_t flags)
{
        uint8_t *value = attr->user_data;
        printk("security level: %d\n", bt_conn_get_security(conn));
        return sizeof(gatt_value);
}

BT_GATT_SERVICE_DEFINE(ess_svc,
        BT_GATT_PRIMARY_SERVICE(BT_UUID_ESS),

        /* Temperature Sensor 1 */
        BT_GATT_CHARACTERISTIC(BT_UUID_TEMPERATURE, (BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE),
                               (BT_GATT_PERM_READ_LESC | BT_GATT_PERM_WRITE_LESC), read_u8,
                               write_u8, &gatt_value),
);

The above is excerpts from code that show the issue, a device can connect and read/write and the handlers will run, security level: 1 can be seen. This is best shown when configured with CONFIG_BT_SMP_SC_ONLY=y and if a pairing cannot take place due to the zephyr bt_conn_set_security call failing.

Impact

Security permission bypass in applications that have assumed that the LESC permission defines work without combining them with other defines.

Patches

main: #69170

embargo: 2024-02-13

For more information

If you have any questions or comments about this advisory:

Severity

High
8.2
/ 10

CVSS base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
Low
Availability
None
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N

CVE ID

CVE-2024-1638

Weaknesses

Credits