在上一篇文章《》当中,我们介绍了蓝牙协议的发展历程及协议规范,接下来我们将介绍蓝牙协议的攻击面以及相关的安全研究成果。
通讯协议安全研究的目标主要包括两个方向:1. 协议设计安全 2.协议实现安全。
协议安全是指协议设计缺陷,出于性能限制、传输速率要求或对安全性考虑不足等原因,很多协议在设计之初并没有充分考虑可能的攻击场景,从而导致协议标准自身就存在各种安全问题。例如广泛运用的HTTP协议在设计之初没有考虑加密问题,在缺少其他协议(如SSL)的保护时,HTTP协议将不得不以明文形式在互联网上进行传输,这也就给了攻击者窃取信息的机会。
实现安全是在编程实现协议标准的过程中引入的软件缺陷,通常是由于代码质量问题以及开发者对协议的理解不一致引入的安全问题。例如,CVE-2021-31166是Windows系统在实现HTTP协议时引入的缓冲区溢出漏洞,该漏洞可能导致远程代码执行、DDoS的严重安全问题。相比设计缺陷而言,软件缺陷在数量级上有质的区别,因为同一个协议标准可能由不同的编程语言或者不同的开发者进行开发,不同开发者对协议的理解也可能存在不一致,进而导致协议在实现时存在诸多安全问题。
历史上蓝牙协议在这两个攻击面上均出现过多个安全漏洞。
1
协议历史漏洞(协议设计缺陷)
1
KNOB
2018年3月,通用协议漏洞KNOB Attack被发现,并在同年10月被报告给了蓝牙SIG和CERT,漏洞编号为CVE-2019-9506。其中,漏洞点主要出现在LMP协议的秘钥协商阶段,一般来说,两个蓝牙设备连接和配对的过程如下:
配对之后会先进行蓝牙秘钥协商,协商过程使用的是配对过程协商的ECDH临时秘钥来加密通信数据。协商过程使用LMP协议,在各自的Controller端实现:
但是LMP entropy协商的阶段并没有经过ECDH的秘钥保护,恶意的攻击者可以使用中间人攻击将熵设置得尽可能小(最小可到1个字节),从而可以通过暴力破解的形式快速破解出Kc’并实时解密蓝牙的传输数据。
因为该漏洞是蓝牙核心协议中的设计漏洞,因此可以影响不同厂商生产的蓝牙芯片,例如Broadcom、CYW、Apple、Snapdragon等蓝牙芯片。
2
BIAS攻击
BIAS全称为Bluetooth Impersonation Attacks,是2020年5月左右公开的蓝牙协议漏洞,漏洞编号为CVE-2020-10135。该漏洞由一系列协议设计缺陷导致的认证错误组成,可以让恶意攻击者连接到未配对的设备。
该漏洞主要是针对传统蓝牙(BR/EDR)的配对过程。在蓝牙协议中,安全配对过程主要分为三个阶段,即Legacy Pairing、SSP和Secure Connection。配对的作用是让从未配对过的设备建立可信、安全的链路层链接。在配对的过程中,我们需要输入一个数字来确认需要配对的蓝牙设备,实际上是两个蓝牙设备协商了一个双方共同持有的长期密钥LTK(Long Term Key),或者说链接秘钥LK(Link Key)。LTK会被用来生成安全链接所使用的的一次性会话密钥(Session Key)。因此两个设备只用配对一次,但可使用保存的LTK进行多次安全连接。
在蓝牙连接的过程中,数据是不经过加密或者校验的。连接建立的主要作用是让两个设备交换它们公开的capability信息、互相校验对方的长期秘钥并计算会话秘钥。如果连接的设备支持Secure Connection,就使用安全连接方法建立链接,连接的过程使用AES-CCM经过加密和完整性保护;否则,就使用Legacy Secure Connection(简称为LSC),连接过程使用E0流加密方法进行加密,并按照对应的流程进行连接。安全连接的建立同样通过LMP协议进行。上述过程存在四个问题:
BIAS漏洞产生的根源是蓝牙协议中不严谨的定义,比如为了兼容性允许Secure Connection降级,并且Role Switch的设计完全没有考虑安全性,对其发起的时机不加判断导致被滥用。从漏洞危害来看,BIAS的直接影响是可以绕过了手动确认的配对认证与目标设备进行连接,一个典型的例子是可以伪造成目标电脑或手机曾经配对过的蓝牙耳机设备,并静默地与目标进行连接,从而实现间接控制扬声器和麦克风的效果。
3
Blacktooth攻击
Blacktooth是研究人员在2022年公开的蓝牙协议漏洞,该漏洞是一系列设计缺陷导致的未配对设备可未授权连接的安全问题,最终通过权限提升漏洞实现敏感信息读取。
为了在两个蓝牙设备之间建立安全连接,Master首先从Slave获取设备名称和功能。然后,Master发送一个连接请求,以启动连接建立。但需要注意的是,设备角色不是固定的——蓝牙协议规范仅将Master定义为启动连接的设备。也就是说,任意的蓝牙BR/EDR设备都可以启动一个连接并成为Master,而不管其功能或以前的角色如何。例如,蓝牙耳机通常是Slave设备,但它也可以作为Master角色,并主动启动与智能手机的连接。在建立连接后,设备可以切换主从角色。这是Blacktooh攻击可以实施的关键因素,因为攻击者可以利用这个缺陷伪装成被攻击设备已经配对成功的设备,并通过角色转换来通过绕过授权机制。
如上图所示,Blacktooth攻击主要包含四个步骤:
第一步,Mallory(攻击者)首先通过将其蓝牙地址修改为Bob的设备地址来模拟Bob(Slave),然后主动向Alice发送一个连接请求,以便通过蓝牙BR/EDR触发连接进程,并强制Alice进入Slave角色,以便在用户没有感知的情况下建立蓝牙连接。
第二步,Mallory使用 Legacy Authentication验证与Alice建立安全连接,以便Alice(Slave)不会对Mallory(Master)进行身份验证。
第三步,Mallory主动向Alice发送请求将通信密钥设置为1个字节,这样即可在不知道任何包括链接密钥()在内的预共享秘密的情况下,通过暴力破解获得加密密钥’。
最后,Mallory可连接到Alice的敏感配置文件,注入恶意命令(使用HID配置文件),并检索Alice的敏感数据(使用PBAP配置文件)。在此基础上,Mallory获得了Alice的完全控制权,Mallory可以向被攻击者发送任意按键,点击任意按钮、检索通讯录、截图屏幕,关机等敏感操作。
2
实现历史漏洞(协议实现缺陷)
1
BleedingTooth漏洞
BleedingTooth是2020年公开的由一系列中高危漏洞组成的Linux蓝牙零点击远程代码执行漏洞,可在用户未被授权的远程攻击者在近距离内对存在漏洞的设备以内核权限执行任意代码。BleedTooth由三个漏洞组成:BadVibes(CVE-2020-24490)、BadChoice(CVE-2020-12352)、BadKarma(CVE-2020-12351)。
BadVibes是Linux内核4.19引入的堆缓冲区溢出溢出漏洞,是HCI事件解析器hci_le_ext_adv_report_evt在解析远程设备的播报时引入的。
static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
u8 num_reports = skb->data[0];
void *ptr = &skb->data[1];
hci_dev_lock(hdev);
while (num_reports--) {
struct hci_ev_le_ext_adv_report *ev = ptr;
u8 legacy_evt_type;
u16 evt_type;
evt_type = __le16_to_cpu(ev->evt_type);
legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type);
if (legacy_evt_type != LE_ADV_INVALID) {
process_adv_report(hdev, legacy_evt_type, &ev->bdaddr,ev->bdaddr_type,
NULL, 0, ev->rssi,ev->data, ev->length);
}
ptr += sizeof(*ev) + ev->length;
}
hci_dev_unlock(hdev);
}
这个方法在调用process_adv_report时,没有检查ev->length是否小于HCI_MAX_AD_LENGTH=31,而这部分数据最终会保存到discovery结构体的last_adv_data字段中
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/bluetooth/hci_event.c
static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 bdaddr_type, s8 rssi, u32 flags,u8 *data, u8 len)
{
struct discovery_state *d = &hdev->discovery;
...
memcpy(d->last_adv_data, data, len);d->last_adv_data_len = len;
}
该字段的长度为31,而在蓝牙5中解析器理论上可以接收最多 255 字节的数据包并将其路由到该方法。如果可能的话,我们可以溢出 last_adv_data 并污染成员直到偏移 0xbaf。
// pahole -E -C hci_dev --hex bluetooth.ko
struct hci_dev {
...
struct discovery_state {
...
/* typedef u8 -> __u8 */ unsigned char last_adv_data[31];
/* 0xab0 0x1f */
...
} discovery; /* 0xa68 0x88 */
...
struct list_head {
struct list_head * next;
/* 0xb18 0x8 */struct list_head * prev;
/* 0xb20 0x8 */
} mgmt_pending; /* 0xb18 0x10 */
...
/* size: 4264, cachelines: 67, members: 192 */
/* sum members: 4216, holes: 17, sum holes: 48 */
/* paddings: 10, sum paddings: 43 */
/* forced alignments: 1 */
/* last cacheline: 40 bytes */
} __attribute__((__aligned__(8)));
BadChoice是a2mp_send()处理 A2MP 协议的 A2MP_GETINFO_REQ 指令中发现的漏洞。这个漏洞在 Linux 内核 3.6引入,并且默认是开启的。
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/bluetooth/a2mp.c
static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,struct a2mp_cmd *hdr)
{
struct a2mp_info_req *req = (void *) skb->data;
...
hdev = hci_dev_get(req->id);
if (!hdev || hdev->dev_type != HCI_AMP) {
struct a2mp_info_rsp rsp;
rsp.id = req->id;
rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp),&rsp);
goto done;
}
...
}
这段代码首先使用 HCI 设备 id 来请求 AMP 控制器的信息。然而,如果设备 id 是无效的或者不是 HCI_AMP 类型,A2MP_STATUS_INVALID_CTRL_ID将会被返回给发送者,但是a2mp_info_rsp包含的多个成员并没有被完全初始化,从而导致内核数据被泄露。
BadKarma是一个类型混淆漏洞,在l2cap_data_rcv()函数中,当 ERTM(增强型重传模式)或者流模式被使用时,我们可以看到 sk_filter() 被调用来处理chan->data:
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/bluetooth/l2cap_core.c
static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
{
...
if ((chan->mode == L2CAP_MODE_ERTM ||
chan->mode == L2CAP_MODE_STREAMING) && sk_filter(chan->data, skb))
goto drop;
...
}
而从下面的可以看出chan->data的类型是struct amp_mgr,而不是struct sock,因此存在内存混淆漏洞。
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/bluetooth/a2mp.c
static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
{
struct l2cap_chan *chan;
int err;
chan = l2cap_chan_create();
if (!chan)
return NULL;
...
chan->mode = L2CAP_MODE_ERTM;
...
return chan;
}
...
static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn, bool locked)
{
struct amp_mgr *mgr;
struct l2cap_chan *chan;
mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
if (!mgr)
return NULL;
...
chan = a2mp_chan_open(conn, locked);
if (!chan) {
kfree(mgr);
return NULL;
}
mgr->a2mp_chan = chan;
chan->data = mgr;
...
return mgr;
}
2
BlueFrag
BlueFrag是2020年2月在Android安全通告中公开的一个可导致RCE的严重缓冲区溢出漏洞,可影响Android蓝牙子系统。该漏洞是HCI层为上层数据提供数据分片重组功能时引入的漏洞。当蓝牙模块处于启用状态时,攻击者可以利用蓝牙守护程序实现远程代码执行。
前面我们提到,HCI为BR/EDR无线电、基带控制器和链路管理器提供了访问蓝牙基带功能、硬件状态和控制寄存器的单一标准接口。从蓝牙协议栈来看,HCI 层位于蓝牙协议栈高层协议和低层协议之间。HCI通过包的方式来传送数据、命令和事件,所有在主机和主机控制器之间的通信都以包的形式进行,包括每个命令的返回参数都通过特定的事件包来传输。HCI有数据、命令和事件三种类型的包。命令包COMMAND(0x01)只能从主机发往主机控制器,其中数据包是双向的,分为两类:ACL(0x02)、SCO(0x03),而事件包EVENT(0x04)始终是主机控制器发向主机的。主机发出的大多数命令包都会触发主机控制器产生相应的事件包作为响应,在传输过程中会有一个句柄,用于识别主机之间的逻辑通道和控制器,共有三种类型的句柄:连接句柄、逻辑链路句柄和物理链路句柄。
L2CAP是基于分组的,但也遵循信道传输的通信模型。L2CAP支持的信道有两种:面向连接的信道和面向无连接的信道,这两种类型的信道间的关系类似于TCP和UDP的关系。L2CAP层将分组数据包封装成HCI层的ACL数据包之后再通过空口发送出去,如果分组数据包过大,超过了HCI单个PDU的大小,单个L2CAP的数据包将被拆分多个分片发送出去。
BlueFrag漏洞产生于分片重组的过程,当分片数据包的长度超过重组数组剩余空间的长度时,会使用重组数据的剩余长度替换分片数据包的长度,但是在计算这个长度时,没有考虑到packet->len可能小于packet->offset(也就是HCI_ACL_PREAMBLE_SIZE)的情况,从而导致整数负溢并最终引起缓冲区溢出。
static void reassemble_and_dispatch(UNUSED_ATTR BT_HDR *packet) {
...
packet->offset = HCI_ACL_PREAMBLE_SIZE;
uint16_t projected_offset = partial_packet->offset + (packet->len - HCI_ACL_PREAMBLE_SIZE);
if (projected_offset > partial_packet->len) { // len stores the expected length
LOG_WARN(LOG_TAG, "%s got packet which would exceed expected length of %d.""Truncating.", __func__, partial_packet->len);
packet->len = partial_packet->len - partial_packet->offset;
projected_offset = partial_packet->len;
}
memcpy(partial_packet->data + partial_packet->offset, packet->data + packet->offset, packet->len - packet->offset);
...
}
3
BlueBorne漏洞
BlueBorne是Armis于2017年公开的一组蓝牙漏洞,是蓝牙协议栈首批公开的严重漏洞,影响了多个平台和操作系统,涉及到的漏洞如下:
这些漏洞组合之后可以实现远程RCE,是蓝牙协议栈中比较具有影响力的一批漏洞。
3
蓝牙模糊测试
模糊测试技术在协议安全性测试中广泛应用,主要的实现思路是通过随机输入大量畸形的交互数据来发现软件中可能存在的漏洞和错误,这些畸形数据包括无效数据、边界值数据、异常数据等各种可能触发软件缺陷的数据。对于蓝牙协议栈而言,可以使用不同方法对不同协议层次进行模糊测试。从测试方法来看,可对状态迁移及数据格式进行测试。从协议层次来看,可以测试HCI、L2CAP等底层协议,以及上层的SDP、BNEP等中间层协议,也可以测试SPP、GATT等上层协议。
目前,针对蓝牙协议模糊测试的安全研究有很多,下面给大家介绍比较有代表性的研究:
1.《L2Fuzz: Discovering Bluetooth L2CAP Vulnerabilities Using Stateful Fuzz Testing》
论文针对L2CAP协议做了优化,主要是做了两方面的工作:一、考虑每个字段的特征,如固定字段(Fixed Fields)、依赖字段 (Dependent Fields)、核心可变字段、应用可变字段(Mutable Application Fields),在变异的过程中,尽量避免变异固定字段和依赖字段,以避免报文被拒绝,同时将变异重心放在核心可变字段上。二、如下图所示,L2CAP连接的建立和关闭涉及到多种状态切换,针对不同状态间的切换过程进行测试以寻找状态转换时存在的错误。
2.《Frankenstein: Advanced Wireless Fuzzing to Exploit New Bluetooth Escalation Targets》
论文主要研究的是将运行在蓝牙芯片上的固件以模拟执行的形式运行起来,同时提供虚拟IO接口来模拟芯片与系统内核之间的交互,在此基础之上提供相应的畸形数据作为输入来测试固件对蓝牙协议数据的处理过程。通过这种方法,研究者发现了三个Broadcom和Cypress芯片上蓝牙协议栈的0day漏洞。
总结
蓝牙协议是一个非常复杂且广泛应用的协议,随着物联网技术的发展,蓝牙协议也深入到了IOT设备的使用中。由于历史原因以及兼容性问题,蓝牙协议在协议设计及协议实现两个攻击面都发现过严重的漏洞,利用漏洞可实现短距离无接触攻击,因此是非常好的研究方向。
参考资料
为了更好的探索与分享前沿趋势和技术研究内容,云起无垠发起并运营了GPTSecurity知识社区,致力打造成一个汇聚GPT、AIGC和LLM在安全领域应用的知识库,共同推动安全领域智能革命的发展。
(点击跳转)
· GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区,集成了生成预训练 Transformer(GPT)、人工智能生成内容(AIGC)以及大型语言模型(LLM)等安全领域应用的知识。在这里,您可以找到关于GPT/AIGC/LLM最新的研究论文、博客文章、实用的工具和预设指令(Prompts)。
· Github地址:
扫描添加小云 加入GPTSecurity交流群
———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: wxii2p22