[하루한줄] CVE-2025-10456 : Zephyr RTOS의 BLE의 검증 미흡으로 인한 DoS

URL

Target

  • Zephyr RTOS의 BLE <= v4.1

Explain

CVE-2025-10456은 Zephyr RTOS의 BLE(Bluetooth Low Energy)에서 발생한 DoS 취약점입니다. 해당 취약점은 Bluetooth 프로토콜 스택 상에서 물리계층과 그 상위계층 간의 통신을 지원하는 L2CAP 계층에서 integer overflow를 방지하기 위한 코드로 부터 발생했습니다. 원인이 된 코드는 BLE의 L2CAP 처리 코드에서 발견되었기 때문에 Bluetooth에서는 트리거 되지 않으며 BLE에서만 트리거가 가능합니다.

취약점이 발견된 곳은 L2CAP Flow Control Credit Indication 요청을 처리하는 l2cap.c의 le_credits() 함수 입니다.

static void le_credits(struct bt_l2cap *l2cap, uint8_t ident,
		       struct net_buf *buf)
{
	struct bt_conn *conn = l2cap->chan.chan.conn;
	struct bt_l2cap_chan *chan;
	struct bt_l2cap_le_credits *ev = (void *)buf->data;
	struct bt_l2cap_le_chan *le_chan;
	uint16_t credits, cid;
	...
	cid = sys_le16_to_cpu(ev->cid);
	credits = sys_le16_to_cpu(ev->credits);

	le_chan = BT_L2CAP_LE_CHAN(chan);

	if (atomic_get(&le_chan->tx.credits) + credits > UINT16_MAX) { //[1] trigger point
		LOG_ERR("Credits overflow");
		bt_l2cap_chan_disconnect(chan); //disconnect when integer overflow
		return;
	}

코드의 [1]에서 credits는 16비트 필드이며 tx.creditsatomic_t 이기 때문에 tx.credits+credits의 값이 65,535 이상일 경우 integer overflow이 발생할 수 있기 때문에 UINT16_MAX를 한계값으로 검사하고 있습니다. 이후 해당 채널의 연결을 종료시키기 위해 bt_l2cap_chan_disconnect()를 호출하게 됩니다.

int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
{
	struct bt_conn *conn = chan->conn;
	struct net_buf *buf;
	struct bt_l2cap_disconn_req *req;
	struct bt_l2cap_le_chan *le_chan;

	if (!conn) {
		return -ENOTCONN;
	}

	if (IS_ENABLED(CONFIG_BT_CLASSIC) && //[*]
	    conn->type == BT_CONN_TYPE_BR) {
		return bt_l2cap_br_chan_disconnect(chan);
	}

	le_chan = BT_L2CAP_LE_CHAN(chan);

	LOG_DBG("chan %p scid 0x%04x dcid 0x%04x", chan, le_chan->rx.cid, le_chan->tx.cid);

	le_chan->ident = get_ident(); // alloc new ID to channel

	buf = l2cap_create_le_sig_pdu(BT_L2CAP_DISCONN_REQ,
				      le_chan->ident, sizeof(*req));
	if (!buf) {
		return -ENOMEM;
	}

	req = net_buf_add(buf, sizeof(*req)); // [2] request packet struct
	req->dcid = sys_cpu_to_le16(le_chan->tx.cid);
	req->scid = sys_cpu_to_le16(le_chan->rx.cid);

	l2cap_chan_send_req(chan, buf, L2CAP_DISC_TIMEOUT); // [3] send disconnect msg
	bt_l2cap_chan_set_state(chan, BT_L2CAP_DISCONNECTING);

	return 0;
}

이후 해당 함수의 코드 [2]에서 해당 채널의 tx.cid, rx.cidreq 구조체에 담아 연결 해제를 위한 메시지를 코드의 [3] 함수 호출을 통해 전송합니다.

| 코드의 [*] 부분으로 인해 해당 취약점은 Bluetooth에는 영향을 미치지 않습니다.

static void le_disconn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
			   struct net_buf *buf)
{
	struct bt_conn *conn = l2cap->chan.chan.conn;
	struct bt_l2cap_le_chan *chan;
	struct bt_l2cap_disconn_rsp *rsp = (void *)buf->data;
	uint16_t scid;

	if (buf->len < sizeof(*rsp)) {
		LOG_ERR("Too small LE disconn rsp packet size");
		return;
	}

	scid = sys_le16_to_cpu(rsp->scid);

	LOG_DBG("dcid 0x%04x scid 0x%04x", sys_le16_to_cpu(rsp->dcid), scid);

	chan = l2cap_remove_rx_cid(conn, scid);
	if (!chan) {
		return;
	}

	bt_l2cap_chan_del(&chan->chan);
}

하지만 이후 request를 처리하는 le_disonn_rsp()에서 cid 값에 대한 검증이 존재하지 않아 고정된 CID 값을 가지는 중요한 서비스들(LE SIGNAL CHANNEL, SMP, ATT …)에 대해 연결해제가 가능해져 DoS 공격이 발생합니다.

Reference



본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.