Android蓝牙组件误差连连看
宣布时间 2018-08-151、概述
Android系统中,蓝牙组件可以说是清静误差重灾区,2017年ArmisSecurity清静团队宣布BlueBorne组合误差攻击链可以通过蓝牙对智能手机举行远程攻击,危害性极大。今年三月份的Android清静通告中,系统层误差所有都是蓝牙组件误差,总共10个。误差多漫衍在SDP(服务发明协议)和BNEP(蓝牙网络封装协议)中,并且误差类型多是内存越界读写。四月份的清静通告中,总共有7个蓝牙组件误差,多漫衍在AVRCP(音频/视频远程控制设置文件)协议中。六月份和七月份Android 清静通告中依然披露了多个蓝牙组件误差,涉及蓝牙协议栈中多个协议,涉及的源码版本为6.0、 6.0.1、 7.0、 7.1.1、7.1.2、 8.0、 8.1,笼罩规模较广。
本文将先容蓝牙协议栈中的L2CAP协媾和SMP协议,并对CVE-2018-9359和CVE-2018-9365这两个误差案例举行详细剖析。
2、协议简介
2.1 L2CAP
L2CAP(Logical Link Control and Adaptation Protocol)称为逻辑链路和适配协议,是蓝牙系统中的焦点协议,位于数据链路层。L2CAP通过协议多分复用、分段和重组,向高层提供面向毗连和无毗连的数据服务。
2.1.1 L2CAP数据包名堂
L2CAP是基于分组的,但也遵照信道传输的通讯模子。L2CAP支持的信道有两种:面向毗连的信道和面向无毗连的信道。在面向毗连的信道中,L2CAP数据包的名堂如下图所示。
数据包中每个字段的说明如下所示:
2.1.2 L2CAP信令
两台蓝牙装备通过L2CAP协议通讯时,所有的信令都被发送到CID为0x0001的信道中。L2CAP信令的名堂如下所示。
L2CAP信令中每个字段的说明如下所示:
L2CAP协议共有12种信令类型,各信令的作用如下表所示。
另外,多个信令可以在统一个帧中发送,如下图所示。
2.2 SMP
SMP(Security Manage Protocol)是蓝牙协议栈中的清静管理协议,认真蓝牙装备之间的配对和密钥分派。
SMP下令名堂如下图所示。
其中,Code字段为一个8bit,标识下令的类型。SMP下令的类型如下表所示。Data字段在长度上是可变的, Code字段决议Data字段的名堂。
3、误差原理剖析
3.1 CVE-2018-9359
(以下剖析基于android-8.0.0_r4版本源码)
CVE-2018-9359误差位于L2CAP协议�?�,误差类型是越界读�?梢酝ü雀韫俜酵ǜ婵吹轿蟛畈苟�。误差补丁代码位于/stack/l2cap/l2c_main.cc文件中的process_l2cap_cmd函数中,该函数主要功效是处置惩罚吸收的L2CAP协议的信令包。
从代码291行最先,while循环剖析L2CAP数据包中所有的COMMAND下令。首先看一下两个宏界说:STREAM_TO_UINT8从p指向的数据包中读取1个字节,p指针加1;STREAM_TO_UINT16每次从p指向的数据包中读取2个字节,p指针加2。
程序挪用宏依次从p指向的数据包中读取cmd_code、id和cmd_len字段,此时p应该指向data数据域的开头。
当Code=0x1,代表Command reject数据包,数据包界说如下所示。当Length不为0,data数据域中包括两个字段:Reason字段(2字节)和Data字段。
处置惩罚Command reject数据包的分支代码如下:
从代码可以看出,程序没有判断该下令包是否保存data数据域,在334行中直接使用宏读取2个字节的rej_reason。因此在内存堆中爆发越界读误差。
这里也执偾爆发了内存越界读取,没有将读取的数据泄露到客户端中。下面找到发送返回包的代码,审查怎样爆发内存走漏。
从378行代码最先是剖析L2CAP_CMD_CONN_REQ下令分支,379行代码,先越界读取两个字节的con_info.psm,380行代码越界读取两个字节的rcid。381行挪用l2cu_find_rcb_by_psm函数通过con_info.psm去遍历寻找注册控制块地址。这里简朴先容一下PSM这个看法。
PSM全称为Protocol/ServiceMultiplexer,PSM的长度最少是2字节,它的值应当是奇数,就是最低的byte的最低位必需为1。另外,PSM的最高byte的最低位应当为0。它可以比2字节长,PSM由两个规模段组成,第一个规模段是SIG用来体现对应protocol的,第二个规模段是动态申请的和SDP团结使用。这个值用来支持特定protocol的差别实现。以是,在申请PSM的时间都是从0x1001最先申请的。缘故原由就是0x0001~0x0eff都是被SIG保存的。那么这些保存的值都各自对应了哪些protocol呢?详细见下图。
代码382行判断p_rcb是否为NULL,若是为空就挪用l2cu_reject_connection函数,详细看一下该函数代码。
从代码520行到523行,通过宏UINT6_TO_STREAM将数据写入p指向的内存中。
其中remote_cid就是之前越界读取的两个字节数据。结构好响应数据包后,代码525行挪用l2c_link_check_send_pkts将响应包发送到客户端。
在六月份android清静通告中,CVE-2018-9359、CVE-2018-9360、CVE-2018-9361三个误差的补丁是一样的。部分补丁代码如下。
可以看出,补丁中添加了长度判断。若是p+2>p_next_cmd不为真,说明保存data数据域,然后才最先读取字节。
3.2 CVE-2018-9365
(以下剖析基于android-8.0.0_r4版本源码)
CVE-2018-9365是SMP(security manager protocol)协议中一个数组越界误差。该误差泛起在smp_sm_event函数中,代码路径为:\smp\smp_main.cc。谷歌官方补丁代码如下。
从补丁中可以看到,这里判断了p_cb->role是否大于1,若是大于1报错返回,补丁代码下一行就是以p_cb->role为下标在smp_entry_table数组中查找。Smp_entry_table数组界说如下。
可以看到,smp_entry_table数组中只有两项,一个是针对主装备,一个是针对从装备。当有数据包通过L2CAP在SMP信道中吸收到时,会挪用smp_data_received函数举行处置惩罚。Smp_data_received函数代码如下。
代码146行定位到内存中SMP数据包位置。代码150行通过STREAM_TO_UINT8宏取出cmd。
第160行代码判断cmd的类型是否为配对请求指令或者清静请求指令。若是是,第164行最先对p_cb->role举行复制。通过名称判断,L2CA_GetBleConnRole函数应该是通过蓝牙地址获取蓝牙装备的角色信息。关于蓝牙装备来说,只有两种角色,一是主装备角色,二是从装备角色。L2CA_GetBleConnRole函数代码如下。
第201行界说了role,同时给role赋值为HCI_ROLE_UNKNOWN。宏界说如下所示。
Role先被复制为0xff,代码205行是通过蓝牙地址遍历寻找p_lcb,若是p_lcb为空,则直接返回HCI_ROLE_UNKNOWN。P_cb->role被赋值为0xff后,后续代码直接挪用了smp_sm_event函数。代码如下所示。
挪用smp_sm_event函数,补丁前的代码在957行由于没有判断p_cb->role的巨细,导致数组越界会见。
4、总结
通过对多个蓝牙误差的剖析,发明Android蓝牙组件中的误差多是较为初级的代码bug导致的,并且误差多泛起在对数据包的剖析代码逻辑中。针对披露的这么多蓝牙误差,安卓手机用户还需实时更新官方推送的补丁,将清静隐患降低到最低。
5、相关链接
[1] https://android.googlesource.com/platform/system/bt/+/b66fc16410ff96e9119f8eb282e67960e79075c8%5E%21/#F0
[2] https://android.googlesource.com/platform/system/bt/+/ae94a4c333417a1829030c4d87a58ab7f1401308%5E%21/#F0
[3] https://blog.quarkslab.com/a-story-about-three-bluetooth-vulnerabilities-in-android.html


京公网安备11010802024551号