作者:启明星辰ADLab

一、概述

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.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.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的大小,导致数组越界访问。

四、总结

通过对多个蓝牙漏洞的分析,发现Android蓝牙组件中的漏洞多是较为低级的代码bug导致的,而且漏洞多出现在对数据包的解析代码逻辑中。针对披露的这么多蓝牙漏洞,安卓手机用户还需及时更新官方推送的补丁,将安全隐患降低到最低。

相关链接

  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

启明星辰积极防御实验室(ADLab)

ADLab成立于1999年,是中国安全行业最早成立的攻防技术研究实验室之一,微软MAPP计划核心成员。截止目前,ADLab通过CVE发布Windows、Linux、Unix等操作系统安全或软件漏洞近400个,持续保持国际网络安全领域一流水准。实验室研究方向涵盖操作系统与应用系统安全研究、移动智能终端安全研究、物联网智能设备安全研究、Web安全研究、工控系统安全研究、云安全研究。研究成果应用于产品核心技术研究、国家重点科技项目攻关、专业安全服务等。


源链接

Hacking more

...