西湖论剑IOT蓝牙
西湖论剑IOT蓝牙
前言
转载文章,记录学习
来源
https://xuanxuanblingbling.github.io/wireless/ble/2021/06/26/ble/
蓝牙协议
协议简介
新老并存是蓝牙协议栈复杂的主要原因,协议分层如图:
[](https://xuanxuanblingbling.github.io/assets/pic/bluetooth/protocal.png)
想了解最全面的蓝牙协议栈设计,可以去 蓝牙官网 找,目前最新的白皮书是:Bluetooth Core Specification v5.3。
协议实现
谈协议分层总是很简单,因为上面这种图片随处可见,但其本质的内容是一个抽象的设计方案,而不是具体的实现方案(软件代码,硬件电路)。对于黑客来说,我们不仅仅关注抽象的协议设计上有没有问题,更关注的是协议的实现,因为设计一般都是经过世界上顶尖的大脑们反复推敲出来的,而实现可能就是某个开发者半夜一边吃外卖一边写出来的。协议设计的问题可能在白皮书中隐约看到,但实现的漏洞你是不可能从白皮书中看出来的,比如:
- Bleeding Tooth:Linux蓝牙驱动远程代码执行分析与利用
- bluetooth_stack开源蓝牙协议栈源码分析与漏洞挖掘
- 物联网安全拔“牙”实战——低功耗蓝牙(BLE)初探
- 记一次智能印章设备的漏洞挖掘
这些漏洞他们的本体在:
- linux内核:linux-5.4/net/bluetooth/a2mp.c
- STM32应用代码:Bluetooth stack: Fix three stack overflow in att messages
- github上暴露的签名算法:miband/model/UserInfo.java
- android APP上不安全的秘钥使用:displayGattServices
所以我们要了解的是,整个蓝牙的通信过程中,其数据处理的每一个过程究竟在哪?换种说法就是:每层的协议到底是软件实现还是硬件实现?如果是软件实现,那是什么层次的软件(应用代码、内核代码、还是芯片固件等等)?也就是具体协议的落地层次,可以参考:
主要就是三种架构方案,后两者的最大区别是:蓝牙app的业务代码与蓝牙协议栈是否运行在同一个处理器上。当然这也就会造成两者蓝牙模组/SoC的开发厂商提供的SDK的本质不同,单芯片的SDK主要完成编译烧录运行,而双芯片主要完成通信过程。
[](https://xuanxuanblingbling.github.io/assets/pic/bluetooth/realization.png)
PC和手机一般用蓝牙的都是host+controller双芯片标准架构,其通信的HCI协议也是蓝牙官方规定好的。通过分析linux的蓝牙驱动,以及相关芯片的datasheet,都能看出来这些芯片不参与任何上层协议的实现工作:
- linux/drivers/bluetooth
- Which mobile device has which bluetooth chip?
- 手机中的蓝牙模块一般是用什么芯片?
- BCM4330
- csr1010-data-sheet
- BCM4354 Datasheet
而嵌入式设备上的使用的蓝牙,可能会采用单芯片整体方案或者自定义双芯片架构,也就是那些蓝牙模组/SoC。模组,模块,SoC其实这些概念用起来比较混淆:
可见网上卖的大部分模组,模块,使用起来都应该属于自定义双芯片架构,因为你看上面的开发,配置一下串口然后就能直接使用GATT协议进行工作了,可见模组中已经实现了比较完整的蓝牙协议栈了。单芯片整体方案最常见的例子就是ESP32,我们的业务代码和蓝牙协议栈代码都运行在一个处理器上:
从 ESP32拆解图 可见:ESP32中就封装了一个ESP的SoC和flash
[](https://xuanxuanblingbling.github.io/assets/pic/bluetooth/esp32.png)
攻击技能
这里只讨论从空口对另一台蓝牙设备的攻击,不讨论本地对自身的蓝牙驱动或者蓝牙芯片的攻击。
对于协议的抽象设计和实现方法有了清晰的认知之后,就是什么东西实现在哪?怎么实现的? 我们从开发者的视角切换成攻击者。我们不仅会对漏洞的发现,原理更加明晰,而且还能更清楚的知道,我们如何发动一次攻击:即在什么协议层次?怎么发送攻击流量?怎么完成这个层次的流量抓取? 此时我们需要回答一个问题:
- 问:基本所有的手机或电脑本身都是支持蓝牙的,那为什么还要其他的外置硬件才能进行某些场景下的安全研究呢?
- 答:研究一个通信的过程,黑客主要有五个动作:收、发、抓、断、改。本机的硬件可能不支持某些动作,比如发畸形链路层报文:[CC2541 SweynTooth BLE漏洞实测](http://iotbzw.com/2020/05/17/CC2541 SweynTooth BLE漏洞实测/)、抓空中其他设备的通信报文等等。
对于空中信号,完成基于中间人的断、改,一般通过拉长双方距离,然后采用中继设备来实现中间人,比如NFCGate。不过除了在通信的物理链路上做手脚,还可以在通信过程的软件实现处完成中间人,就像可以使用frida来hook掉android侧的app进而完成对蓝牙数据的修改一样,只要在关注的目标层次之前,篡改其未来要处理的数据即可。对于蓝牙的中间人我还没有调研过,这里还是主要说,收、发、抓这三个动作。
层次抓包
其实在通信过程的任何阶段,都可以想办法捕获通信内容,所说的常规方法只不过因为是现成的方案。
蓝牙抓包一般来说有如下几种办法:
方法 | 抓包位置 | 所需硬件 | 特点 | 方法说明 |
---|---|---|---|---|
Ubertooth | 空口 | Ubertooth | BLE/BR, open source | 使用Ubertooth监听蓝牙通信 |
nRF52832 | 空口 | nRF52832 | only BLE | nRF52832 Sniffer 抓包使用体验 |
cc2540 | 空口 | cc2540 | only BLE | CC2540 USB Dongle 蓝牙抓包分析仪使用教程 |
hollong | 空口 | hollong | only BLE | Hollong 蓝牙4.0/4.1/4.2 BLE协议监控分析仪 文档 |
HCI接口 | 本机 | 本机蓝牙 | only local | 使用Ubuntu虚拟机抓Bluetooth报文 |
HCIlog | 本机 | 本机蓝牙 | only local | Android Bluetooth HCI log 详解 |
抓包位置不同,捕获的数据包层次就不同,看起来的样子也不同,主要是两种,空口和HCI:
- 使用ubertooth抓取的空口报文:HITCTF 2020 蓝牙原始数据解析
- 使用HCIlog在Android上抓取的蓝牙报文:android下的蓝牙HCI日志抓取方法
但是以上两个都不够直观,我们使用接下来的例题自己抓两个包:
- HCI 报文(wireshark抓取主机HCI接口):adv_hci.pcapng
- 空口报文(hollong抓取的空中信号):adv_hollong.pcapng
可以清楚的对比两种报文的差异了,其实大差不差:
[](https://xuanxuanblingbling.github.io/assets/pic/bluetooth/snifer_hci.png)
HCI和空口是蓝牙协议栈的不同层次,协议对两个层次的数据组织并不是简单的封装。这个差异最开始很让我困惑,因为我们太熟悉以太网的报文了,以至于理所应当的认为:数据在通信的每一个层次的流动就是简单做一些数据的包裹,即添加或删除一些头之类的操作。但其实数据在他的整个生命周期的过程,除了基本的包裹操作,还可以有非常多的变换,比如加密解密,编码解码等。这里的本质原因是:每个层次所考虑的问题不仅仅是对下层负责,可能还要在本层完成一些事情。
高级收发
攻击行为本质就是恶意数据的收发,任何包含发送数据的攻击都必然要有攻击的信道。
如果只是BLE应用层(ATT流量)的简单读写交互的话,nRF connect 这个手机软件就足够了,但当我们需要:
- 攻击经典蓝牙
- 在ATT层有复杂的交互
- 攻击其他非ATT的底层协议
这时 nRF connect 就有些力不从心了,于是我们需要更高级的收发包方法,让我们能构造更丰富的恶意报文,所以我们需要尽量彻底的控制蓝牙设备,让其为我们工作。刚才我们说过,目前的手机以及PC都采用的是host+controller双芯片标准架构,所以由于硬件的限制,一般来说,我们只能构造链路层以上的报文。对于链路层和物理层的攻击,则需要更加可控的蓝牙设备,比如ESP32,[Nordic52840](http://iotbzw.com/2020/05/17/CC2541 SweynTooth BLE漏洞实测/),甚至是自己构建的SDR。这里我们只关注PC和手机平台作为攻击机:
攻击机 | 蓝牙设备 | 协议栈 | 原生API | 顶层工具 |
---|---|---|---|---|
linux PC | PC蓝牙controller | bluez | D-Bus API、C socket API | bluez tools、Scapy、pybluez、bluepy、pygatt、bluescan |
android | 手机蓝牙controller | Fluoride | java API | nRF connect |
iPhone | 手机蓝牙controller | 私有 | Objective-C API | nRF connect |
bluez API 说明:Linux Bluetooth API Function Locations
在以上原生API的帮助下,我们在空口收发包的最低层次能到L2CAP。值得注意的是,HCI层协议是主机和控制器的交互界面,其自身的生命周期只存在于二者交互的过程中,而不存在于纯空口过程中。所以对于从空口上完成的HCI层攻击,还是发送其他层协议的报文,从而触发对端的HCI过程,进而发生攻击。
- CVE-2020-0022 an Android 8.0-9.0 Bluetooth Zero-Click RCE – BlueFrag
- Android 蓝牙子系统 “BlueFrag” 漏洞分析(CVE-2020-0022)
- 蓝牙安全与攻击案例分析: bluefrag
- CVE-2020-0022漏洞分析
不过原生API的使用不够便捷与轻量,而linux的蓝牙攻击工具是生态最成熟的,基本都是python的库,只有bluez自带的用户态二进制工具除外。所以linux的PC是我们理想的攻击平台,但由于我们大都是使用linux虚拟机,其使用蓝牙设备的方式是和宿主机共享,在这种情况下可能会出现各种各样的问题,所以一般建议linux虚拟机独占一个蓝牙外设。比如我媳妇的惠普windows本中的linux虚拟机就可以使用共享本机的蓝牙设备正常攻击,而我的 MacBook Pro 上,虽然可以使用hciconfig看到蓝牙设备,但之后无法正常进行攻击,这里使用bluepy中的blescan进行测试。
所以当你尝试共享蓝牙设备给linux虚拟机不好使的情况下,才可能需要单独购买一个蓝牙USB外设。bluescan的官方文档中建议Ostran 奥视通 USB 蓝牙适配器 OST-105 CSR 8150 v4.0或者UD100 G03,我之前一直很奇怪为啥非得这俩蓝牙外设,他们多啥?这玩意淘宝一搜不一大堆么?后来仔细看看才发现,原来网上卖的蓝牙USB外设大部分没有linux的驱动,都是windows独占。另外这些蓝牙USB外设的信号也没有手机或者PC上自带的蓝牙芯片稳定,经常需要插拔,重新连接到虚拟机等重置操作。外设配置好后,就可以关注怎么控制外设收发包了,即linux上的蓝牙顶层工具,这些工具是各有特色:
工具 | 形态 | 底层 | 接口最低控制层次 | 特点 |
---|---|---|---|---|
bluez tools | 命令行 | bluez | HCI(BR/BLE) | 基础:主要用于配置检查,能完成一些基本的正常业务数据包 |
Scapy | python | bluez | HCI(BR/BLE) | 收发:使用复杂,可在python层面直接控制HCI,组织数据包灵活 |
pybluez | python | bluez | L2CAP(BR/BLE) | 收发:成熟的python蓝牙库,对L2CAP、RFCOMM层的接口友好 |
bluepy | python | bluez | GATT (BLE) | 收发:GATT相关处理较多,扫描脚本blescan命令行直接可用 |
pygatt | python | gatttool | GATT (BLE) | 收发:将gatttool(bluez tools)封装成python接口 |
bluescan | python | bluepy , pybluez | HCI(BR/BLE) | 扫描:安恒海特实验室 Sourcell Xu 开发,安全向,主要用于扫描,Python 3.9以上适配 |
工具使用示例文章:
有了这些工具,学会了怎么使用这些工具配置,发包,扫描,就可以完成下面的题目了。