neustes

Die leise Gefahr im Smartphone: Wie BLE-Scanner zur Überwachung werden

Autor: DerSchneider

Das Smartphone ist längst zum ständigen Begleiter avanciert – ein multifunktionales Werkzeug, das uns vernetzt, informiert und unterhält. Doch während wir die Annehmlichkeiten der mobilen Konnektivität genießen, läuft im Hintergrund ein permanenter Austausch von Datenpaketen, der kaum Beachtung findet. Eine dieser Technologien, Bluetooth Low Energy (BLE), ist aus dem Alltag nicht mehr wegzudenken und ermöglicht eine Vielzahl von Anwendungen – vom kabellosen Kopfhörer bis zum Türöffner. Dass diese allgegenwärtige Funktechnologie jedoch nicht nur Komfort bietet, sondern auch ein bislang unterschätztes Risiko für die Privatsphäre birgt, zeigen aktuelle Entwicklungen und Forschungsarbeiten. Was auf den ersten Blick wie ein harmloses Hilfsmittel zur Geräteortung erscheint, entpuppt sich bei näherer Betrachtung als potenzielles Werkzeug für eine flächendeckende Überwachung.

Der trügerische Schein der Anonymität

Die eigentliche Herausforderung im Bereich des BLE-Schutzes liegt nicht in der Abschottung, sondern in der permanenten Sichtbarkeit. Ein modernes Smartphone sendet im aktiven Zustand kontinuierlich Signale aus, um sich mit seiner Umgebung zu vernetzen. Diese „Advertising Packets“ sind notwendig, damit andere Geräte es „sehen“ und eine Verbindung anfragen können. In einer Forschungsumgebung wurde gezeigt, wie einfach es ist, diese Signale nicht nur zu empfangen, sondern sie auch systematisch auszuwerten.

Ein vollständiger BLE-Scanner als Beispiel

Um die technische Umsetzung zu veranschaulichen, zeigt der folgende, vollständige Code einen funktionsfähigen BLE-Scanner für den ESP32, wie er in vielen privaten Projekten zu finden ist. Die Kommentare im Code zeigen bereits die Richtung an, in die solche Systeme weiterentwickelt werden.

cpp

/*
 * BLE Scanner für CYD mit Anwesenheits-Historie und E-Mail-Benachrichtigungen
 * 
 * Features:
 * - Live-Anzeige aller Geräte
 * - Historie der letzten 50 Erkennungen
 * - E-Mail bei neuem Gerät
 * - E-Mail bei Gerät verschwunden
 * - 24h Übersicht per E-Mail
 * - Touchscreen zum Umschalten zwischen Live-Ansicht und Historie
 */

#include <TFT_eSPI.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <WiFi.h>
#include <ESP_Mail_Client.h>
#include <XPT2046_Touchscreen.h>  // Touchscreen-Bibliothek

// ============================================================
// 📝 WIFI & E-MAIL KONFIGURATION
// ============================================================
const char* WIFI_SSID = "DEIN_WLAN_NAME";
const char* WIFI_PASS = "DEIN_WLAN_PASSWORT";

const char* EMAIL_ABSENDER = "deine.email@gmail.com";
const char* EMAIL_PASSWORT = "dein_app_passwort";
const char* EMAIL_EMPFANGER = "empfaenger@email.de";
const char* SMTP_SERVER = "smtp.gmail.com";
int SMTP_PORT = 587;

// ============================================================
// 📝 DISPLAY KONFIGURATION
// ============================================================
TFT_eSPI tft = TFT_eSPI();

// ============================================================
// 📝 TOUCH KONFIGURATION
// ============================================================
#define TOUCH_CS 12
XPT2046_Touchscreen ts(TOUCH_CS);
uint16_t touchX, touchY;
bool touchPressed = false;

// ============================================================
// 📝 DEINE PERSÖNLICHE NAMENSLISTE
// ============================================================
struct BekanntesGeraet {
  String mac;
  String name;
};

BekanntesGeraet bekannteGeraete[] = {
  {"AA:BB:CC:DD:EE:01", "Mama"},
  {"AA:BB:CC:DD:EE:02", "Papa"},
  {"AA:BB:CC:DD:EE:03", "Alex"},
};

int anzahlBekannt = sizeof(bekannteGeraete) / sizeof(bekannteGeraete[0]);

// ============================================================
// 📝 HISTORIE & ANWESENHEIT
// ============================================================
struct HistorienEintrag {
  String name;
  String mac;
  unsigned long zeitstempel;
  int rssi;
};

#define MAX_HISTORIE 50
HistorienEintrag historie[MAX_HISTORIE];
int historieAnzahl = 0;
int historieIndex = 0;

struct Anwesenheit {
  String mac;
  String name;
  unsigned long letzteSichtung;
  bool istAnwesend;
  unsigned long anwesenheitsBeginn;
  unsigned long gesamteAnwesenheit;
};

#define MAX_GERAETE 20
Anwesenheit geräte[MAX_GERAETE];
int anzahlGeräte = 0;

// ============================================================
// 📝 GLOBALE VARIABLEN
// ============================================================
BLEScan* pBLEScan;
int scanTime = 3;
int pauseTime = 2;
bool zeigeHistorie = false;
unsigned long letzteEmailZeit = 0;
unsigned long tagStartZeit = 0;
const unsigned long TAG_IN_SEKUNDEN = 86400;

SMTPSession smtp;

// ============================================================
// FUNKTION: MAC -> Name
// ============================================================
String getNameFuerMAC(String mac) {
  mac.toUpperCase();
  for (int i = 0; i < anzahlBekannt; i++) {
    String bekannteMAC = bekannteGeraete[i].mac;
    bekannteMAC.toUpperCase();
    if (bekannteMAC == mac) {
      return bekannteGeraete[i].name;
    }
  }
  return "Unbekannt";
}

// ============================================================
// FUNKTION: Historie hinzufügen
// ============================================================
void fuegeHistorieHinzu(String name, String mac, int rssi) {
  if (historieAnzahl > 0) {
    int letzterIndex = (historieIndex - 1 + MAX_HISTORIE) % MAX_HISTORIE;
    if (historie[letzterIndex].mac == mac) {
      historie[letzterIndex].zeitstempel = millis();
      historie[letzterIndex].rssi = rssi;
      return;
    }
  }
  
  historie[historieIndex].name = name;
  historie[historieIndex].mac = mac;
  historie[historieIndex].zeitstempel = millis();
  historie[historieIndex].rssi = rssi;
  
  historieIndex = (historieIndex + 1) % MAX_HISTORIE;
  if (historieAnzahl < MAX_HISTORIE) {
    historieAnzahl++;
  }
}

// ============================================================
// FUNKTION: Anwesenheit aktualisieren
// ============================================================
void aktualisiereAnwesenheit(String name, String mac, int rssi) {
  unsigned long jetzt = millis() / 1000;
  
  for (int i = 0; i < anzahlGeräte; i++) {
    if (geräte[i].mac == mac) {
      if (!geräte[i].istAnwesend) {
        geräte[i].istAnwesend = true;
        geräte[i].anwesenheitsBeginn = jetzt;
        if (name != "Unbekannt") {
          sendeEmail("✅ " + name + " ist da!", 
                     name + " wurde soeben erkannt.\nRSSI: " + String(rssi) + " dBm");
        }
      }
      geräte[i].letzteSichtung = jetzt;
      return;
    }
  }
  
  if (anzahlGeräte < MAX_GERAETE) {
    geräte[anzahlGeräte].mac = mac;
    geräte[anzahlGeräte].name = name;
    geräte[anzahlGeräte].letzteSichtung = jetzt;
    geräte[anzahlGeräte].istAnwesend = true;
    geräte[anzahlGeräte].anwesenheitsBeginn = jetzt;
    geräte[anzahlGeräte].gesamteAnwesenheit = 0;
    anzahlGeräte++;
    
    if (name != "Unbekannt") {
      sendeEmail("🆕 Neues Gerät: " + name,
                 name + " (" + mac + ") wurde zum ersten Mal gesehen.");
    }
  }
}

// ============================================================
// FUNKTION: Abwesenheit prüfen
// ============================================================
void prüfeAbwesenheit() {
  unsigned long jetzt = millis() / 1000;
  unsigned long abwesenheitsSchwelle = 30;
  
  for (int i = 0; i < anzahlGeräte; i++) {
    if (geräte[i].istAnwesend && 
        (jetzt - geräte[i].letzteSichtung) > abwesenheitsSchwelle) {
      geräte[i].istAnwesend = false;
      geräte[i].gesamteAnwesenheit += (jetzt - geräte[i].anwesenheitsBeginn);
      
      if (geräte[i].name != "Unbekannt") {
        sendeEmail("❌ " + geräte[i].name + " weg!",
                   geräte[i].name + " wurde nicht mehr gesehen.\n" +
                   "War " + String(jetzt - geräte[i].anwesenheitsBeginn) + " Sekunden da.");
      }
    }
  }
}

// ============================================================
// FUNKTION: 24h Übersicht
// ============================================================
void sendeTagesübersicht() {
  String nachricht = "📊 24h Anwesenheitsübersicht\n\n";
  nachricht += "Zeitraum: Letzte 24 Stunden\n";
  nachricht += "================================\n\n";
  
  for (int i = 0; i < anzahlGeräte; i++) {
    if (geräte[i].name != "Unbekannt") {
      unsigned long gesamt = geräte[i].gesamteAnwesenheit;
      if (geräte[i].istAnwesend) {
        gesamt += (millis() / 1000 - geräte[i].anwesenheitsBeginn);
      }
      
      unsigned long stunden = gesamt / 3600;
      unsigned long minuten = (gesamt % 3600) / 60;
      
      nachricht += "👤 " + geräte[i].name + "\n";
      nachricht += "   Anwesend: " + String(stunden) + "h " + String(minuten) + "m\n";
      nachricht += "   Status: " + String(geräte[i].istAnwesend ? "🟢 Jetzt da" : "🔴 Nicht da") + "\n";
      nachricht += "   Letzte Sichtung: " + String((millis() / 1000 - geräte[i].letzteSichtung) / 60) + " min her\n\n";
    }
  }
  
  if (nachricht.length() < 100) {
    nachricht += "Keine bekannten Geräte erkannt.\n";
    nachricht += "Warte auf erste Sichtung...\n";
  }
  
  sendeEmail("📊 Tägliche Anwesenheitsübersicht", nachricht);
  tagStartZeit = millis() / 1000;
}

// ============================================================
// FUNKTION: E-Mail senden
// ============================================================
void sendeEmail(String betreff, String nachricht) {
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("❌ WiFi nicht verbunden!");
    return;
  }
  
  if (millis() - letzteEmailZeit < 10000) {
    Serial.println("⏳ E-Mail zu oft, warte...");
    return;
  }
  
  Serial.println("📧 Sende E-Mail: " + betreff);
  letzteEmailZeit = millis();
  
  smtp.debug(0);
  
  ESP_Mail_Session session;
  session.server.host_name = SMTP_SERVER;
  session.server.port = SMTP_PORT;
  session.login.email = EMAIL_ABSENDER;
  session.login.password = EMAIL_PASSWORT;
  session.login.user_domain = "gmail.com";
  
  SMTP_Message message;
  message.sender.name = "BLE Scanner";
  message.sender.email = EMAIL_ABSENDER;
  message.subject = betreff;
  message.message = nachricht;
  message.addRecipient("Empfänger", EMAIL_EMPFANGER);
  
  if (!smtp.connect(&session)) {
    Serial.println("❌ SMTP-Verbindung fehlgeschlagen!");
    return;
  }
  
  if (!MailClient.sendMail(&smtp, &message)) {
    Serial.println("❌ E-Mail fehlgeschlagen: " + smtp.errorReason());
  } else {
    Serial.println("✅ E-Mail gesendet!");
  }
  
  smtp.closeSession();
}

// ============================================================
// FUNKTION: Display initialisieren
// ============================================================
void initDisplay() {
  tft.init();
  tft.setRotation(1);
  tft.invertDisplay(true);
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.setTextSize(2);
}

// ============================================================
// FUNKTION: Touch initialisieren
// ============================================================
void initTouch() {
  ts.begin();
  ts.setRotation(1);
  Serial.println("✅ Touch initialisiert!");
}

// ============================================================
// FUNKTION: Touch lesen
// ============================================================
bool touchErkannt() {
  if (ts.touched()) {
    TS_Point p = ts.getPoint();
    if (!touchPressed) {
      touchPressed = true;
      touchX = p.x;
      touchY = p.y;
      
      // Nur auf Touch im oberen Bereich reagieren (Statusleiste)
      if (p.x > 0 && p.x < 320 && p.y > 0 && p.y < 50) {
        return true;
      }
    }
  } else {
    touchPressed = false;
  }
  return false;
}

// ============================================================
// FUNKTION: Live-Ansicht
// ============================================================
void zeigeLiveAnsicht(BLEScanResults foundDevices) {
  tft.fillScreen(TFT_BLACK);
  
  tft.setTextColor(TFT_CYAN, TFT_BLACK);
  tft.setTextSize(2);
  tft.setCursor(10, 10);
  tft.println("📡 BLE Scanner");
  
  tft.setTextColor(TFT_GREEN, TFT_BLACK);
  tft.setTextSize(1);
  tft.setCursor(10, 35);
  tft.print("Gefunden: ");
  tft.print(foundDevices.getCount());
  
  tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
  tft.setCursor(200, 35);
  tft.setTextSize(1);
  tft.print("[Touch]");
  
  int deviceCount = foundDevices.getCount();
  int maxDisplay = 7;
  
  if (deviceCount == 0) {
    tft.setTextColor(TFT_ORANGE, TFT_BLACK);
    tft.setTextSize(2);
    tft.setCursor(10, 80);
    tft.println("Keine Geräte");
  } else {
    for (int i = 0; i < deviceCount && i < maxDisplay; i++) {
      BLEAdvertisedDevice device = foundDevices.getDevice(i);
      String mac = device.getAddress().toString().c_str();
      int rssi = device.getRSSI();
      String name = getNameFuerMAC(mac);
      
      int yPos = 60 + (i * 30);
      tft.fillRect(10, yPos - 5, 300, 30, TFT_BLACK);
      
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setTextSize(2);
      tft.setCursor(10, yPos);
      tft.print(name);
      
      tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
      tft.setTextSize(1);
      tft.setCursor(160, yPos + 2);
      if (mac.length() > 8) tft.print(mac.substring(0, 8) + "...");
      else tft.print(mac);
      
      int xPosRSSI = 250;
      tft.setCursor(xPosRSSI, yPos + 2);
      if (rssi > -50) tft.setTextColor(TFT_GREEN, TFT_BLACK);
      else if (rssi > -70) tft.setTextColor(TFT_YELLOW, TFT_BLACK);
      else tft.setTextColor(TFT_RED, TFT_BLACK);
      tft.setTextSize(1);
      tft.print(rssi);
      tft.print("dBm");
      
      if (name != "Unbekannt") {
        aktualisiereAnwesenheit(name, mac, rssi);
        fuegeHistorieHinzu(name, mac, rssi);
      }
    }
  }
  
  tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
  tft.setTextSize(1);
  tft.setCursor(10, 300);
  tft.print("Historie: ");
  tft.print(historieAnzahl);
  tft.print(" | Geräte: ");
  tft.print(anzahlGeräte);
}

// ============================================================
// FUNKTION: Historie anzeigen
// ============================================================
void zeigeHistorieAnsicht() {
  tft.fillScreen(TFT_BLACK);
  
  tft.setTextColor(TFT_CYAN, TFT_BLACK);
  tft.setTextSize(2);
  tft.setCursor(10, 10);
  tft.println("📜 Anwesenheit");
  
  tft.setTextColor(TFT_GREEN, TFT_BLACK);
  tft.setTextSize(1);
  tft.setCursor(10, 35);
  tft.print("Letzte ");
  tft.print(historieAnzahl);
  tft.print(" Ereignisse");
  
  tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
  tft.setCursor(200, 35);
  tft.setTextSize(1);
  tft.print("[Touch]");
  
  if (historieAnzahl == 0) {
    tft.setTextColor(TFT_ORANGE, TFT_BLACK);
    tft.setTextSize(2);
    tft.setCursor(10, 80);
    tft.println("Keine Historie");
    return;
  }
  
  int maxAnzeige = 8;
  int startIndex = (historieIndex - 1 + MAX_HISTORIE) % MAX_HISTORIE;
  
  for (int i = 0; i < maxAnzeige && i < historieAnzahl; i++) {
    int idx = (startIndex - i + MAX_HISTORIE) % MAX_HISTORIE;
    HistorienEintrag eintrag = historie[idx];
    
    int yPos = 60 + (i * 28);
    tft.fillRect(10, yPos - 5, 300, 28, TFT_BLACK);
    
    tft.setTextColor(TFT_WHITE, TFT_BLACK);
    tft.setTextSize(2);
    tft.setCursor(10, yPos);
    tft.print(eintrag.name);
    
    tft.setTextColor(TFT_YELLOW, TFT_BLACK);
    tft.setTextSize(1);
    tft.setCursor(120, yPos + 2);
    unsigned long alter = (millis() - eintrag.zeitstempel) / 1000;
    if (alter < 60) tft.print(alter); else tft.print(alter/60);
    tft.print(alter < 60 ? "s alt" : "m alt");
    
    tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
    tft.setCursor(250, yPos + 2);
    tft.setTextSize(1);
    tft.print(eintrag.rssi);
    tft.print("dBm");
  }
}

// ============================================================
// SETUP
// ============================================================
void setup() {
  Serial.begin(115200);
  Serial.println("Starte BLE Scanner mit E-Mail...");
  
  initDisplay();
  initTouch();  // Touch initialisieren
  
  Serial.print("Verbinde mit WiFi...");
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  int versuche = 0;
  while (WiFi.status() != WL_CONNECTED && versuche < 20) {
    delay(500);
    Serial.print(".");
    versuche++;
  }
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\n✅ WiFi verbunden! IP: " + WiFi.localIP().toString());
  } else {
    Serial.println("\n❌ WiFi Verbindung fehlgeschlagen!");
  }
  
  BLEDevice::init("CYD-Scanner");
  pBLEScan = BLEDevice::getScan();
  pBLEScan->setActiveScan(true);
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);
  
  tagStartZeit = millis() / 1000;
  Serial.println("✅ Bereit!");
}

// ============================================================
// LOOP
// ============================================================
void loop() {
  if (touchErkannt()) {
    zeigeHistorie = !zeigeHistorie;
    delay(300);
  }
  
  unsigned long jetzt = millis() / 1000;
  if (jetzt - tagStartZeit >= TAG_IN_SEKUNDEN) {
    sendeTagesübersicht();
  }
  
  if (zeigeHistorie) {
    zeigeHistorieAnsicht();
    delay(1000);
  } else {
    Serial.println("🔍 Scanne...");
    BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
    Serial.print("📱 Gefunden: ");
    Serial.println(foundDevices.getCount());
    
    zeigeLiveAnsicht(foundDevices);
    prüfeAbwesenheit();
    
    pBLEScan->clearResults();
    delay(pauseTime * 1000);
  }
}

Dieser Code ist ein Paradebeispiel dafür, wie viel Macht in wenigen Zeilen Code steckt. Er scannt nicht nur die Umgebung, sondern speichert auch eine Historie, verfolgt Anwesenheitszeiten und versendet sogar E-Mail-Benachrichtigungen. In einem privaten Smart-Home-Szenario, etwa um die Anwesenheit von Familienmitgliedern zu erkennen, mag dies zunächst harmlos erscheinen. Die zugrundeliegende Technik ist jedoch dieselbe, die auch für weitaus kritischere Anwendungen genutzt werden kann.

Die dünne Grenze zwischen Komfort und Kontrolle

Die eigentliche Brisanz entfaltet sich, wenn man die möglichen Erweiterungen eines solchen Scanners bedenkt. Die folgende Tabelle zeigt, wie schnell aus einem harmlosen Anwesenheitssensor ein mächtiges Überwachungswerkzeug werden kann.

FunktionBeschreibungPotenzielle Gefahr
MAC-Adress-LoggingSpeicherung aller gesehenen MAC-Adressen mit ZeitstempelErstellung von Bewegungsprofilen
Historie & AnalyseSpeicherung von Anwesenheitszeiten und -häufigkeitenDetaillierte Einblicke in Alltagsroutinen
E-Mail-BenachrichtigungAutomatischer Versand von Nachrichten bei bestimmten EreignissenSofortige Information über die Abwesenheit einer Person
Externe DatenanbindungSenden der Daten an einen Cloud-Dienst oder ServerZentralisierung und Missbrauch von Bewegungsdaten

Gefährliche Erweiterungen: Vom Scanner zum Überwachungssystem

Die im Code gezeigten Funktionen sind nur der Anfang. Erweiterungen könnten das System in ein noch mächtigeres Werkzeug verwandeln:

  • Automatische Profilerstellung: Durch die Verknüpfung von MAC-Adressen mit Orten und Zeiten ließe sich ein detailliertes Bewegungsprofil jeder erfassten Person erstellen.
  • Vernetzung mehrerer Scanner: Ein Netzwerk aus mehreren Scannern könnte die Bewegung von Personen durch ganze Gebäude oder Stadtviertel verfolgen.
  • Kopplung mit anderen Datenquellen: Die Kombination mit WLAN-Scans, Kamerasystemen oder sozialen Medien würde eine nahezu lückenlose Überwachung ermöglichen.
  • KI-gestützte Analyse: Mithilfe von künstlicher Intelligenz ließen sich Verhaltensmuster erkennen und sogar Vorhersagen über zukünftige Aufenthalte treffen.

Kein Einzelfall: Der ESP32 und seine dokumentierten Debug-Funktionen

Die Gefahr wird durch die weite Verbreitung des Mikrocontrollers ESP32 potenziert. Dieser Chip ist in über einer Milliarde Geräten weltweit verbaut und stand aufgrund einer spektakulären Entdeckung im Fokus der Sicherheitsforschung. Im März 2025 berichtete die spanische Firma Tarlogic Security, dass der ESP32 undokumentierte Befehle enthält – sogenannte „versteckte Funktionen“, die ursprünglich für Debugging- und Testzwecke vorgesehen waren.

Diese Entdeckung führte zunächst zu Besorgnis, da die Befehle potenziell eine Hintertür in milliardenfähigen Geräten darstellen könnten. Eine genauere Analyse durch den Hersteller Espressif und unabhängige Sicherheitsexperten relativierte die Gefahr jedoch deutlich. Es stellte sich heraus, dass es sich nicht um eine böswillig eingebaute Backdoor handelt, sondern um interne Debug-Funktionen, die:

  • nicht aus der Ferne (remote) ausgenutzt werden können – Angreifer müssten physischen Zugang zum Gerät haben,
  • keine Internetverbindung benötigen, um genutzt zu werden, dafür aber privilegierte Zugriffsrechte auf dem System voraussetzen,
  • als „schlechte Praxis“ des Herstellers gelten, aber kein aktives Sicherheitsrisiko für Endanwender darstellen.

Espressif reagierte umgehend auf die Berichterstattung, stellte die Funktionen klar und kündigte an, die entsprechenden Debug-Befehle in zukünftigen Chip-Revisionen zu entfernen oder besser zu dokumentieren. Die Sicherheitslücke wurde unter der Kennung CVE-2025-27840 registriert.

Dennoch wirft der Vorfall ein grelles Licht auf die Verwundbarkeit der globalen IoT-Infrastruktur. Die Tatsache, dass ein für wenige Euro erhältlicher Chip undokumentierte Funktionen enthalten kann, zeigt die Dringlichkeit, die Sicherheit von BLE-Systemen zu überdenken. Auch wenn die ESP32-Debug-Befehle selbst keine unmittelbare Gefahr darstellen, bleibt das zugrundeliegende Problem bestehen: Die Fähigkeit, BLE-Signale passiv zu erfassen und auszuwerten, ermöglicht eine neue Ära der Überwachung.

Ein Ausblick in die gläserne Gesellschaft

Die hier beschriebenen Techniken sind keine Zukunftsmusik mehr, sondern bereits heute im Einsatz. Die Fähigkeit, BLE-Signale passiv zu erfassen und auszuwerten, hat eine neue Ära der Überwachung eingeläutet. Die scheinbare Anonymität im öffentlichen Raum ist längst zur Illusion geworden, denn jedes mitgeführte Smartphone sendet unermüdlich eine eindeutige Kennung aus. Zwar haben die Hersteller mit der MAC-Adress-Randomisierung eine Schutzmaßnahme eingeführt, doch wie aktuelle Forschungen zeigen, lassen sich Geräte dennoch über Verhaltensmuster oder andere statische Identifikatoren in den Broadcast-Daten identifizieren.

Die rechtlichen Rahmenbedingungen, insbesondere die Datenschutz-Grundverordnung (DSGVO) in Europa, versuchen zwar, Grenzen zu ziehen, doch die technologische Entwicklung läuft ihnen oft davon. Es bedarf daher nicht nur eines Bewusstseinswandels bei den Nutzern, die den Umgang mit ihren Geräten hinterfragen sollten, sondern auch eines Umdenkens bei den Herstellern. Die Integration von Sicherheitsmaßnahmen wie Secure Boot, authentifizierten Firmware-Updates und einer robusten Verschlüsselung ist kein optionales Extra, sondern eine Notwendigkeit, um das Vertrauen in die digitalen Technologien zu bewahren.

Der leichte Umgang mit dem Smartphone und seinen Funktionen führt uns geradewegs in eine Welt, in der das eigene Gerät zum stillen Kronzeugen gegen einen selbst wird. Der gezeigte Code ist dabei nur ein kleiner Ausschnitt des Möglichen – ein Beispiel dafür, wie einfach es ist, mit wenigen Zeilen Code eine Überwachungsinfrastruktur aufzubauen. Es ist an der Zeit, diese Entwicklung kritisch zu hinterfragen und sich der Tatsache bewusst zu werden, dass die Technologie, die uns verbindet, uns auch gläsern machen kann.


Quellen

  • Tarlogic Security: „Undocumented Commands Found in Espressif’s ESP32 Chip“ (2025) – inzwischen durch Hersteller und CERT klarstellend ergänzt
  • Espressif Systems: Offizielle Stellungnahme zu CVE-2025-27840 (März 2025)
  • INCIBE (spanisches CERT): Sicherheitshinweis zu CVE-2025-27840
  • IEEE Xplore: „A Survey on Bluetooth Low Energy Security“ (2024)
  • Datenschutz-Grundverordnung (DSGVO) – EU-Verordnung 2016/679
  • Espressif Systems: ESP32 Technical Reference Manual
  • USENIX Security Symposium: „BLE Location Tracking“ (2023)

Kommentar abschicken

Das hast du vielleicht verpasst