BLE-Relais — Bedrohungsmodell

Was ein Angreifer tun kann, der den Firmware-Quellcode kennt, aber keinen Zugriff auf die Geheimnisse des Geräts hat.

Angriffsfläche

Die Firmware ist öffentlich, daher sind Paketformate, Längen und Algorithmen (X25519, HMAC-SHA256, HKDF) bekannt. BLE ist offener Funk, daher lassen sich Advertisements und GATT-Schreibvorgänge mithören. Weder in der Firmware noch im Funk steckt ein Geheimnis.

Wo die Schlüssel liegen:

Was ein Angreifer nicht kann

AttackDefence
Ein FIRE fälschenHMAC-SHA256. Ohne owner_secret oder guest_key ist das ein 2128 -Brute-Force — nicht machbar.
Einen TIME-Schreibvorgang fälschenDerselbe HMAC über bleId + epochMs.
Ein mitgeschnittenes Advertisement wiederholenDer Zähler ist monoton: bei Wiederholung oder Rückgang passt der HMAC nicht.
Ein mitgeschnittenes FIRE wiederholenDer Nonce-Ring entwertet bereits benutzte Nonces.
Die Uhr des Controllers zurückstellenDie Ratsche: jedes TIME < Ratsche wird abgelehnt. Die Ratsche liegt im NVS und übersteht einen Stromausfall.
Ein abgelaufenes Bundle verwendenNach dem Betrieb des Controllers liegt die Ratsche mindestens bei der letzten echten Zeit. Bei einem abgelaufenen Bundle liegt validUntil unter der Ratsche, das FIRE scheitert an der Gültigkeit.
Die Uhr ein Jahr vorstellen und alle Gäste aussperrenBegrenzung von +24 h pro Gast-TIME-Schreibvorgang. Für den Besitzer gilt keine Grenze — ihm wird vertraut.
Sich als zweiter Besitzer über den ersten koppelnNach dem Koppeln hält der Controller owner_secret im NVS und geht ohne Werksreset nie wieder in den Kopplungsmodus.

Was ein Angreifer kann und was es kostet

1. Zeit vorstellen — Dienstverweigerung für legitime Gäste

Requires: ein gültiges, nicht abgelaufenes Gast-Bundle.

Action: bei jeder Annäherung ein TIME schreiben, das 24 Stunden vorspringt.

Limit: +24 h pro Sitzung, und ein frisches FIRE ist nötig, wenn die letzte Synchronisation weniger als eine Stunde her ist. Nach zehn Besuchen steht die Ratsche zehn Tage voraus, und die Tokens der übrigen legitimen Gäste wirken abgelaufen.

Die Kehrseite: Das Token des Angreifers wird an derselben gefälschten Zeit gemessen und läuft dadurch früher ab.

Was tun: Der Besitzer kommt vorbei und schreibt die echte Zeit. Die Ratsche bewegt sich nicht, denn zurück kann sie nicht, aber neue Gast-Tokens werden mit aktuellem validUntil ausgegeben und funktionieren danach für alle. Zur Wiederherstellung genügt es, die Gültigkeit auf dem Server zu erneuern.

Severity: eine vorübergehende Dienstverweigerung bis zum Besuch des Besitzers. Nicht kritisch.

2. Mittelsmann beim Koppeln

Requires: sich in den 90 Sekunden nach dem Start der Kopplung physisch in Reichweite des Controllers befinden.

Action: im Kopplungs-Handshake den eigenen öffentlichen X25519-Schlüssel unterschieben.

Result: Der Controller koppelt sich mit dem Angreifer statt mit dem Besitzer. Der Besitzer hält die Kopplung für gelungen, kann aber vom Telefon aus nichts öffnen.

Aktueller Schutz: nur das Zeitfenster und die physische Anwesenheit des Besitzers — er sieht, dass die Kopplung nicht bestätigt wurde, und wiederholt sie.

Hardening: einen einfachen Bestätigungscode ergänzen — vier Ziffern auf dem Display des Controllers oder im Serial —, den der Besitzer in der App bestätigt. Heute gibt es einen solchen Code nicht.

Severity: Das Fenster ist eng und verlangt Nähe genau in diesen 90 Sekunden. In der Praxis schwer umzusetzen.

3. Physischer Werksreset

Requires: physischer Zugang zum Controller und ein langer Tastendruck.

Action: Das NVS wird gelöscht, owner_secret verschwindet, der Controller kehrt in den Kopplungsmodus zurück.

Result: Der Angreifer koppelt den Controller mit sich, der Besitzer verliert den Zugang.

Defence: den Controller geschützt montieren — in einem Kasten, unter einer Abdeckung.

Severity: dasselbe, wie eine Türsprechanlage von der Tür zu reißen — kein kryptografisches Problem.

4. owner_secret über UART oder JTAG auslesen

Requires: physischer Zugang und ein Flash-Dump bei abgeschaltetem Secure Boot und Flash-Verschlüsselung — beides ist derzeit aus.

Action: das NVS mit owner_secret auslesen.

Result: vollständige Kompromittierung des Geräts und aller Gast-Tokens.

Defence: Secure Boot und Flash-Verschlüsselung des ESP32 aktivieren (efuse, unumkehrbar). Heute nicht aktiviert.

Severity: für den häuslichen Einsatz akzeptabel. An verantwortungsvollen Standorten ist Secure Boot nötig.

5. GATT-Verbindungen blockieren — Dienstverweigerung

Requires: in BLE-Reichweite sein.

Action: verbinden und nie trennen. NimBLE unterstützt nur eine begrenzte Zahl gleichzeitiger Verbindungen.

Result: Legitime Clients kommen nicht durch, solange der Angreifer einen Platz belegt.

Aktueller Schutz: nur die Timeouts von NimBLE.

Hardening: ein Leerlauf-Timeout ergänzen: Hat ein Client binnen 5 Sekunden kein gültiges FIRE ausgeführt, wird die Verbindung getrennt.

Severity: eine vorübergehende Dienstverweigerung, solange der Angreifer in der Nähe ist.

6. Eine Flut ungültiger Schreibvorgänge (Verbindungs-Spoofing)

Action: den Controller mit Müll-Schreibvorgängen bombardieren.

Result: Der Controller verwirft sie und schreibt ins Serial. An seinem Zustand ändert sich nichts, und sobald der Angreifer geht, läuft alles wie gewohnt.

Was bewusst keine Verteidigung ist

Drei Stellen sehen nach Schutz aus und sind keiner. Besser, sie beim Namen zu nennen, als jemanden sich darauf stützen zu lassen.

Das Zustandsbyte im Advertisement trägt ein 16-Bit-Tag. Das genügt gegen zufällige Verfälschung im Funk und nicht mehr: Ein entschlossener Fälscher probiert 16 Bit in Sekunden durch. Das Byte steuert nur die Anzeige „offen/geschlossen“ auf der Karte und gewährt keine Rechte, deshalb bleibt das Tag kurz — jedes zusätzliche Byte kostet bei jedem Aufwachen Akku.

Nur-App-Schlüssel stützen sich auf ein Geheimnis, das im APK steckt. Wer die Datei entpackt, erhält es und fälscht die Attestierung. Das hebt die Hürde gegenüber einem beiläufigen Web-Client, mehr nicht. Die eigentliche Kontrolle für einen solchen Schlüssel ist die Bindung an einen Gerätefingerabdruck — diese Prüfung läuft auf dem Server und hängt nicht davon ab, ob die App ein Geheimnis bewahrt.

Die Gültigkeit eines Gastschlüssels stellt bei BLE der Controller selbst sicher: Das Token trägt eine Frist, und der Controller hat eine Uhr. Bei den übrigen Objekttypen gibt es gar keine Frist — der Schlüssel lebt, bis der Besitzer ihn widerruft. Die App behauptet nichts Gegenteiliges; sollte aber je eine Zeitbegrenzung auch für sie in der Oberfläche auftauchen, muss sie auf dem Server durchgesetzt und nicht auf die Karte gemalt werden.

Fazit

Übliche Härtung für den industriellen Einsatz:

  1. Secure Boot und Flash-Verschlüsselung (Schutz vor JTAG und Dumps).
  2. Ein Bestätigungscode im Kopplungsablauf (Schutz vor dem Mittelsmann).
  3. Ein Leerlauf-Timeout für GATT-Verbindungen (Schutz vor Blockade).
  4. Signaturvergleich in konstanter Zeit — in Firmware und App umgesetzt: Der frühere byteweise Vergleich verriet über die Antwortzeit, wie viele Bytes einer Signatur erraten waren.

Nichts davon ist für die heutigen Szenarien kritisch, doch verantwortungsvolle Standorte haben die Härtung verdient.