Skip to content

Buffer overflow vulnerabilities in the Zephyr Bluetooth subsystem

High
ceolin published GHSA-rgx6-3w4j-gf5j Sep 26, 2023

Package

Zephyr

Affected versions

<= 3.4.0

Patched versions

None

Description

Summary

I spotted a few buffer overflow vulnerabilities at the following locations in the Zephyr Bluetooth subsystem source code:
https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/bluetooth/audio/tbs.c
https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/bluetooth/audio/shell/mcc.c
https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/bluetooth/audio/shell/media_controller.c
https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/bluetooth/host/conn.c
https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/bluetooth/mesh/beacon.c
https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/bluetooth/mesh/prov_device.c
https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/bluetooth/mesh/provisioner.c
https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/bluetooth/mesh/shell/rpr.c

Details

Static buffer overflows in /subsys/bluetooth/audio/tbs.c:

int bt_tbs_remote_incoming(uint8_t bearer_index, const char *to,
			   const char *from, const char *friendly_name)
{
	struct tbs_service_inst *inst;
	struct bt_tbs_call *call = NULL;
	size_t local_uri_ind_len;
	size_t remote_uri_ind_len;
	size_t friend_name_ind_len;
...
	inst = &svc_insts[bearer_index];
...
	if (friendly_name) {
		inst->friendly_name.call_index = call->index;
		(void)strcpy(inst->friendly_name.uri, friendly_name); /* VULN */
		friend_name_ind_len = strlen(from) + 1;
...
	if (IS_ENABLED(CONFIG_BT_GTBS)) {
...
		if (friendly_name) {
			gtbs_inst.friendly_name.call_index = call->index;
			(void)strcpy(gtbs_inst.friendly_name.uri, friendly_name); /* VULN */
			friend_name_ind_len = strlen(from) + 1;
...

Stack-based buffer overflow in /subsys/bluetooth/audio/shell/mcc.c:

#ifdef CONFIG_BT_MCC_OTS
static int cmd_mcc_send_search_raw(const struct shell *sh, size_t argc,
				   char *argv[])
{
	int result;
	struct mpl_search search;

	search.len = strlen(argv[1]);
	memcpy(search.search, argv[1], search.len); /* VULN */
	LOG_DBG("Search string: %s", argv[1]);

	result = bt_mcc_send_search(default_conn, &search);
	if (result) {
		shell_print(sh, "Fail: %d", result);
	}
	return result;
}

Stack-based buffer overflow in /subsys/bluetooth/audio/shell/media_controller.c:

#ifdef CONFIG_BT_OTS
static int cmd_media_set_search(const struct shell *sh, size_t argc, char *argv[])
{
	/* TODO: Currently takes the raw search as input - add parameters
	 * and build the search item here
	 */

	struct mpl_search search;
	int err;

	search.len = strlen(argv[1]);
	memcpy(search.search, argv[1], search.len); /* VULN */
	LOG_DBG("Search string: %s", argv[1]);

	err = media_proxy_ctrl_send_search(current_player, &search);
	if (err) {
		shell_error(ctx_shell, "Search send failed (%d)", err);
	}

	return err;
}

Heap-based buffer overflow in /subsys/bluetooth/host/conn.c:

#if defined(CONFIG_BT_SMP)
...
int bt_conn_le_start_encryption(struct bt_conn *conn, uint8_t rand[8],
				uint8_t ediv[2], const uint8_t *ltk, size_t len)
{
	struct bt_hci_cp_le_start_encryption *cp;
	struct net_buf *buf;

	buf = bt_hci_cmd_create(BT_HCI_OP_LE_START_ENCRYPTION, sizeof(*cp));
	if (!buf) {
		return -ENOBUFS;
	}

	cp = net_buf_add(buf, sizeof(*cp));
	cp->handle = sys_cpu_to_le16(conn->handle);
	memcpy(&cp->rand, rand, sizeof(cp->rand));
	memcpy(&cp->ediv, ediv, sizeof(cp->ediv));

	memcpy(cp->ltk, ltk, len); /* VULN */
	if (len < sizeof(cp->ltk)) {
		(void)memset(cp->ltk + len, 0, sizeof(cp->ltk) - len);
	}

	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_START_ENCRYPTION, buf, NULL);
}

Ineffective size check due to assert and buffer overflow in /subsys/bluetooth/mesh/beacon.c:

void bt_mesh_beacon_priv_random_get(uint8_t *random, size_t size)
{
	__ASSERT(size <= sizeof(priv_random.val), "Invalid random value size %u", size);
	memcpy(random, priv_random.val, size); /* VULN */
}

Static buffer overflow in /subsys/bluetooth/mesh/prov_device.c (conf_size could be 32 and not 16):

static void prov_confirm(const uint8_t *data)
{
	uint8_t conf_size = bt_mesh_prov_auth_size_get();

	LOG_DBG("Remote Confirm: %s", bt_hex(data, conf_size));

	memcpy(bt_mesh_prov_link.conf, data, conf_size); /* VULN */
	notify_input_complete();

	send_confirm();
}

Static buffer overflow in /subsys/bluetooth/mesh/provisioner.c (conf_size could be 32 and not 16):

static void prov_confirm(const uint8_t *data)
{
	uint8_t conf_size = bt_mesh_prov_auth_size_get();

	LOG_DBG("Remote Confirm: %s", bt_hex(data, conf_size));

	if (!memcmp(data, bt_mesh_prov_link.conf, conf_size)) {
		LOG_ERR("Confirm value is identical to ours, rejecting.");
		prov_fail(PROV_ERR_CFM_FAILED);
		return;
	}

	memcpy(bt_mesh_prov_link.conf, data, conf_size); /* VULN */

	send_random();
}

Stack-based buffer overflow in /subsys/bluetooth/mesh/shell/rpr.c:

static void rpr_scan_report(struct bt_mesh_rpr_cli *cli,
			    const struct bt_mesh_rpr_node *srv,
			    struct bt_mesh_rpr_unprov *unprov,
			    struct net_buf_simple *adv_data)
{
	char uuid_hex_str[32 + 1];

	bin2hex(unprov->uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));

	shell_print(bt_mesh_shell_ctx_shell,
		    "Server 0x%04x:\n"
		    "\tuuid:   %s\n"
		    "\tOOB:    0x%04x",
		    srv->addr, uuid_hex_str, unprov->oob);

	while (adv_data && adv_data->len > 2) {
		uint8_t len, type;
		uint8_t data[31];

		len = net_buf_simple_pull_u8(adv_data) - 1;
		type = net_buf_simple_pull_u8(adv_data);
		memcpy(data, net_buf_simple_pull_mem(adv_data, len), len); /* VULN */
		data[len] = '\0';

		if (type == BT_DATA_URI) {
			shell_print(bt_mesh_shell_ctx_shell, "\tURI:    \"\\x%02x%s\"",
				    data[0], &data[1]);
		} else if (type == BT_DATA_NAME_COMPLETE) {
			shell_print(bt_mesh_shell_ctx_shell, "\tName:   \"%s\"", data);
		} else {
			char string[64 + 1];

			bin2hex(data, len, string, sizeof(string));
			shell_print(bt_mesh_shell_ctx_shell, "\t0x%02x:  %s", type, string);
		}
	}
}

PoC

I haven't tried to reproduce these potential vulnerabilities against a live install of the Zephyr OS.

Impact

If the unchecked inputs above are attacker-controlled and cross a security boundary, the impact of the buffer overflow vulnerabilities could range from denial of service to arbitrary code execution.

Patches

This has been fixed in:

For more information

If you have any questions or comments about this advisory:

embargo: 2023-08-19

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Adjacent
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Changed
Confidentiality
Low
Integrity
Low
Availability
Low

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L

CVE ID

CVE-2023-4264

Credits