Linux内核蓝牙协议栈误差(BleedingTooth)使用剖析与复现
宣布时间 2021-04-16误差概述
2020年10月,谷歌清静研究职员披露了三个Linux内核蓝牙协议栈误差,可导致远程代码执行,被称为BleedingTooth。这三个误差中,一个是堆溢出,编号为CVE-2020-24490;另一个是类型混淆,编号为CVE-2020-12351,最后一个是信息泄露,编号为CVE-2020-12352。克日,谷歌清静研究职员又披露了BleedingTooth中CVE-2020-12351和CVE-2020-12352组合的误差使用及细节,并在蓝牙4.0下,实现了零点击远程代码执行。
误差剖析
CVE-2020-12351
该误差泛起在net/bluetooth/l2cap_core.c中。l2cap_recv_frame()是剖析和处置惩罚l2cap协议数据包的函数。代码实现如下所示:

获取通道cid和l2cap数据包长度len。代码实现如下所示:

凭证差别的通道cid,进入差别的子历程举行处置惩罚,进入l2cap_data_channel()函数。代码实现如下所示:

首先,通过cid找到通道chan;若是没有找到,判断cid是否为L2CAP_CID_A2MP;若是是,挪用a2mp_channel_create()建设一个新的通道chan。a2mp_channel_create()函数实现如下所示:

挪用amp_mgr_create()建设mgr,在amp_mgr_create()函数中,代码实现如下所示:

挪用a2mp_chan_open()建设通道chan,该函数将初始化一部分数据,代码实现如下所示:

如将chan->mode初始化为L2CAP_MODE_ERTM。chan->data赋值为mgr,类型为struct amp_mgr。乐成建设a2mp通道返回到l2cap_data_channel()中,代码实现如下所示:

凭证chan->mode的差别,进入差别的data处置惩罚子历程,当mode为L2CAP_MODE_ERTM和L2CAP_MODE_STREAMING时,进入l2cap_data_rcv()函数中,代码实现如下所示:

该if条件中,会挪用sk_filter()函数,此时chan->data为参数。而sk_filter()函数界说如下所示:

第一个参数类型为struct sock,而chan->data类型为struct amp_mgr,爆发类型混淆。
CVE-2020-12352
该误差是泛起在a2mp协议中,误差代码位于net/bluetooth/a2mp.c,多个函数使用未初始化的结构体,将数据返回到用户层,导致信息泄露,可泄露内核栈上的内存数据。误差原理较为简朴,以a2mp_getinfo_req()函数为例,该函数是响应getinfo请求时挪用的,代码实现如下所示:

行304,通过req->id获取hdev,若是不保存hdev或hdev->type不是HCI_AMP,进入if语句中,界说struct a2mp_info_rsp类型的 rsp,该结构体界说如下所示:

其只使用了rsp.id和rsp.status,其他的数据域未使用也未初始化,可以泄露16字节数据,然后挪用a2mp_send()函数将响应包发送到用户层,泄露内存数据。
CVE-2020-24490
该误差只能在bluetooth 5.0下触发,在bluetooth 5.0之前,HCI举行广播的最大数据长度为0x1F,0x20-0xFF保存。如下所示:

在bluetooth 5.0中,该length最大扩展到229字节。如下所示:

该误差代码位于net/bluetooth/hci_event.c中,在处置惩罚HCI_LE_Extended_Advertising_Report事务中,未判断广播数据长度最大值,后续拷贝广播Data导致溢出。挪用历程如下所示:

process_adv_report()函数处置惩罚广播数据,将广播数据拷贝到发明的装备中,代码实现如下所示:

挪用store_pending_adv_report()函数,该函数实现广播数据拷贝,代码实现如下所示:

其中,discovery_state结构体界说如下所示:

last_adv_data数据巨细为HCI_MAX_AD_LENGTH,共31字节,当执行memcpy时爆发溢出。
使用剖析与复现
控制代码执行流程
前文剖析到CVE-2020-12351类型混淆是在sk_filter()函数中爆发的,sk_filter()函数挪用sk_filter_trim_cap()函数,该函数代码实现如下:

该函数第一个参数为sk,参数类型为sock结构体,这部分代码中对sk和skb的检查容易绕过。接下来要害代码如下所示:

行113,对sk->sk_filter举行解引用,若是乐成获取filter指针,进入行115。行119,挪用bpf_prog_run_save_cb()函数,参数划分为filter->prog和skb,该函数代码实现如下所示:

然后,行676,挪用__bpf_prog_run_save_cb()函数,该函数实现代码如下:

接着,行662,挪用BPF_PROG_RUN(prog,skb),该函数界说为一个宏,实现代码如下所示:

一起挪用下来,最终会挪用到红框中的代码,简化一下挪用历程为:
sk->sk_filter->prog->bpf_func(skb, sk->sk_filter->prog->insnsi)。因此,只要控制sk->sk_filter就可以控制执行流程。
堆喷占位
函数sk_filter()的第一个参数类型为struct sock,而现实传入的参数类型为struct amp_mgr,可以接纳堆喷128巨细的内存块举行占位,伪造amp_mgr 工具。这里有个问题,sk->sk_filter在sock中的偏移为0x110,而amp_mgr结构体巨细为0x70,偏移已经凌驾了规模。要解决这个问题,这里可以接纳如下巧妙的堆喷结构:

结构体amp_mgr在kmalloc-128类型的slub中被分派,从第三个块最先,amp_mgr结构体偏移0x10处,可以被伪造成sk_filter,便可以知足sk对sk_filter域的解引用,并且可控。
结构载荷
通过堆喷占位控制代码执行流程后,接下来就是结构攻击载荷�?梢越幽啥雅�1024巨细的内存块去伪造l2cap_chan工具,由于结构体巨细为792,正好落在kmalloc-1024 slub块中,并且a2mp通道也属于l2cap通道中,释放a2mp通道时,l2cap通道也将被释放,操控起来较为无邪,最终结构如下所示:

泄露l2cap_chan工具地址
通过堆喷结构和建设释放l2cap_chan通道等一系列操作后,可能保存一个指向kmalloc-1024内存块地址的l2cap_chan工具,可以通过CVE-2020-12352误差泄露一个内核栈上面的内核地址,如下图中红框所示:

通过该内地地址减去一个0x110偏移便可以找到一个l2cap_chan工具地址,可以通过amp_mgr结构体内存地址检查一下是否准确,由于amp_mgr结构体偏移0x18处为l2cap_chan指针,如下图中红框所示:

乐成泄露l2cap_chan工具地址后,然后去填充amp_mgr结构体偏移0x10处的数据域。
复现测试
我们在ubuntu 5.4.0-26-generic系统下复现测试误差使用,执行历程如下:

乐成反弹root级shell,如下所示:

参考链接:
[1]https://google.github.io/security-research/pocs/linux/bleedingtooth/writeup
[2]https://github.com/google/security-research/security/advisories/GHSA-ccx2-w2r4-x649
[3]https://github.com/google/security-research/security/advisories/GHSA-7mh3-gq28-gfrq
[4]https://github.com/google/security-research/security/advisories/GHSA-h637-c88j-47wq
尊龙凯官网入口起劲防御实验室(ADLab)
ADLab建设于1999年,是中国清静行业最早建设的攻防手艺研究实验室之一,微软MAPP妄想焦点成员,“黑雀攻击”看法首推者。阻止现在,ADLab已通过CVE累计宣布清静误差近1100个,通过 CNVD/CNNVD累计宣布清静误差1000余个,一连坚持国际网络清静领域一流水准。实验室研究偏向涵盖操作系统与应用系统清静研究、智能终端清静研究、物联网智能装备清静研究、Web清静研究、工控系统清静研究、云清静研究。研究效果应用于产品焦点手艺研究、国家重点科技项目攻关、专业清静服务等。



京公网安备11010802024551号