Passives Scanning
Die erste Phase jeder BLE-Sicherheitsanalyse: Informationen sammeln ohne aktive Interaktion.
Warum passiv beginnen?â
- Unentdeckt bleiben
- VollstÀndiges Advertising-Verhalten beobachten
- Potentielle Privacy-Leaks identifizieren
- GerÀte-Landschaft verstehen
Scanning-Methodenâ
1. bluetoothctl (Empfohlen)â
Die moderne Methode fĂŒr Bluetooth LE Scanning:
# Interaktiv
bluetoothctl
[bluetooth]# scan le
# Warte auf Ergebnisse...
[bluetooth]# devices
[bluetooth]# info AA:BB:CC:DD:EE:FF
[bluetooth]# scan off
[bluetooth]# quit
# Oder als Einzeiler
bluetoothctl scan le
2. hcitool (Legacy - nur Bluetooth 4.x)â
Veraltet
hcitool ist deprecated und funktioniert nicht mit Bluetooth 5.x Adaptern!
Bei Bluetooth 5.x GerÀten erhÀltst du: Set scan parameters failed: Input/output error
Verwende stattdessen bluetoothctl scan le.
# Nur fĂŒr Ă€ltere Bluetooth 4.x Adapter:
sudo hciconfig hci0 up
sudo hcitool lescan
3. blatann (Skript-basiert)â
#!/usr/bin/env python3
"""
Passiver BLE Scanner
Sammelt Informationen ohne Verbindungsaufbau
"""
import sys
import time
from blatann import BleDevice
from blatann.utils import setup_logger
def scan_passive(serial_port, duration=30):
setup_logger(level="INFO")
ble_device = BleDevice(serial_port)
ble_device.configure()
ble_device.open()
time.sleep(1)
devices = {}
def on_adv(sender, report):
addr = str(report.peer_address)
adv = report.advertise_data
# Informationen sammeln
info = {
"name": adv.local_name or report.device_name,
"rssi": report.rssi,
"services": [str(u) for u in adv.service_uuids],
"manufacturer_data": adv.manufacturer_data.hex() if adv.manufacturer_data else None,
}
if addr not in devices:
devices[addr] = info
print(f"\n[NEW] {addr}")
print(f" Name: {info['name']}")
print(f" RSSI: {info['rssi']} dBm")
if info['services']:
print(f" Services: {', '.join(info['services'])}")
if info['manufacturer_data']:
print(f" Mfg Data: {info['manufacturer_data']}")
ble_device.scanner.on_scan_received.register(on_adv)
print(f"đ Passiver Scan ({duration}s)...")
print("=" * 50)
ble_device.scanner.set_default_scan_params(timeout_seconds=duration)
ble_device.scanner.start_scan().wait(timeout=duration + 5)
print("=" * 50)
print(f"\nâ
{len(devices)} eindeutige GerÀte")
ble_device.close()
return devices
if __name__ == "__main__":
port = sys.argv[1] if len(sys.argv) > 1 else "/dev/ttyACM0"
scan_passive(port)
Was du beobachten solltestâ
Advertising-Typenâ
| Typ | Beschreibung | Security-Relevanz |
|---|---|---|
| ADV_IND | Connectable, scannable | Standard - verbindbar |
| ADV_DIRECT_IND | Directed advertising | Kann MAC-Adresse leaken |
| ADV_SCAN_IND | Scannable, nicht connectable | Nur Daten, keine Verbindung |
| ADV_NONCONN_IND | Nicht connectable | Beacons, Broadcast-only |
Manufacturer Dataâ
Viele GerÀte senden sensible Daten im Advertising:
# Beispiel: Smart Waage sendet Gewicht im Advertising!
manufacturer_data = bytes.fromhex("c005 1234 5678")
# ^ID ^Gewicht ^Impedanz
Privacy-Leak!
Die Lebenlang Waage sendet das aktuelle Gewicht unverschlĂŒsselt im Advertising-Paket - sichtbar fĂŒr jeden in Reichweite!
Service UUIDsâ
# Standard Bluetooth SIG UUIDs (16-bit)
"0x180F" # Battery Service
"0x180A" # Device Information
"0x1800" # Generic Access
# Custom/Vendor UUIDs (128-bit)
"0000fff0-0000-1000-8000-00805f9b34fb" # Oft fĂŒr Custom Services
Fallstudie: Smart Waage Privacy-Leakâ
#!/usr/bin/env python3
"""
Privacy-Scanner fĂŒr Smart Waagen
Demonstriert wie sensible Daten im Advertising geleakt werden
"""
import sys
import struct
from blatann import BleDevice
TARGET_NAME = "Yoda1"
TARGET_MFG_ID = 0x05C0
def scan_waage(serial_port):
ble_device = BleDevice(serial_port)
ble_device.configure()
ble_device.open()
def on_adv(sender, report):
adv = report.advertise_data
name = adv.local_name
if name and TARGET_NAME.lower() in name.lower():
mfg_data = adv.manufacturer_data
if mfg_data and len(mfg_data) >= 6:
# Gewicht dekodieren (Big Endian)
raw_weight = struct.unpack('>H', mfg_data[2:4])[0]
weight_kg = raw_weight / 100.0
# Impedanz dekodieren
raw_impedance = struct.unpack('>H', mfg_data[4:6])[0]
if weight_kg > 5.0: # Filter leere Messungen
print(f"\nđš PRIVACY-LEAK DETEKTIERT!")
print(f" GerÀt: {report.peer_address}")
print(f" GEWICHT: {weight_kg:.2f} kg")
print(f" IMPEDANZ: {raw_impedance} Ohm")
ble_device.scanner.on_scan_received.register(on_adv)
print(f"đ Scanne nach '{TARGET_NAME}'...")
ble_device.scanner.start_scan().wait(timeout=60)
ble_device.close()
if __name__ == "__main__":
port = sys.argv[1] if len(sys.argv) > 1 else "/dev/ttyACM0"
scan_waage(port)
Dokumentation der Ergebnisseâ
Template fĂŒr Scan-Ergebnisseâ
## Passive Reconnaissance - [GerÀtename]
**Datum**: YYYY-MM-DD
**Dauer**: X Minuten
**Tool**: blatann / hcitool / nRF Sniffer
### Identifizierte GerÀte
| MAC | Name | RSSI | Connectable | Services |
|-----|------|------|-------------|----------|
| AA:BB:CC:DD:EE:FF | Device1 | -65 | â | 0xfff0 |
### Advertising-Analyse
- **Typ**: ADV_IND
- **Intervall**: ~100ms
- **Manufacturer ID**: 0xXXXX
- **Manufacturer Data**: `XX XX XX XX...`
### Potentielle Privacy-Issues
- [ ] Sensible Daten im Advertising?
- [ ] MAC-Adresse rotiert?
- [ ] Tracking möglich?
### NĂ€chste Schritte
1. Wireshark Capture erstellen
2. Manufacturer Data analysieren
3. Aktive GATT-Enumeration
NĂ€chster Schritt
Weiter zur Advertising-Analyse.