flawopen.com/Teardowns/cve-2024-32896-android-factory-reset-wipe-bypass
CVE-2024-32896: Android-Werksreset ließ sich unterbrechen, bevor die Schlüssel vernichtet waren
CVE-2024-32896 (CVSS 7.8, in begrenzten, gezielten Angriffen ausgenutzt): Ein Werksreset startete das Gerät nur in den Recovery-Modus neu und ließ die Verschlüsselungsschlüssel bis zur Löschung unangetastet. Wer das Telefon in der Hand hatte, konnte den Neustart unterbrechen und die Daten wiederherstellbar halten. Der Fix löscht vor dem Neustart alle Keystore-Schlüssel.
Die Regel einer Firma für einen verlorenen Laptop lautet: ihm den Befehl „schreddern“ schicken. Der Laptop geht dann in den Schredderraum, wo alle Dateien vernichtet werden. Wer den Laptop festhält, kann aber unterwegs den Flur versperren – die Dateien kommen nirgends an und bleiben unversehrt. Die Lösung: Bevor er losgeht, verbrennt der Laptop die einzigen Schlüssel zu seinem verschlossenen Aktenschrank. Selbst wenn der Weg unterbrochen wird, kann niemand den Schrank je wieder öffnen.
Kernkonzepte & Begriffe
Werksreset (--wipe_data)- Eine Löschung, angestoßen vom Nutzer, einer Geräteadministrator- oder MDM-App oder einem Fernlöschdienst.
RecoverySystemServiceschreibt den Befehl.rebootRecoveryWithCommand()--wipe_datafür die Recovery und startet neu. Bootloader-Steuerblock (BCB)- Eine kleine Partition (
misc), in der Android Anweisungen für Bootloader und Recovery hinterlegt; geschrieben vonsetupOrClearBcb(). FBE und synthetisches Passwort- Dateibasierte Verschlüsselung. Die Schlüssel der Nutzerdaten leiten sich aus einem synthetischen Passwort ab, dessen Schutz-Blobs an KeyMint-Schlüssel gebunden sind; werden diese vernichtet, sind die Daten nicht mehr entschlüsselbar.
KeyMint / Keystore- Der hardwaregestützte Schlüsseldienst.
AndroidKeyStoreMaintenanceweist jedes KeyMint-Gerät an, alle seine Schlüssel zu löschen..deleteAllKeys()
Ursachenanalyse
rebootRecoveryWithCommand() in RecoverySystemService.java behandelte --wipe_data, indem es den Befehl in den Bootloader-Steuerblock schrieb und neu startete – im Vertrauen darauf, dass die Recovery /data anschließend löscht. Bis diese Löschung fertig war, blieben die KeyMint-Schlüssel, die das synthetische Passwort sowie die DE- und Metadaten-Verschlüsselungsschlüssel schützen, intakt. Wer den Neustart unterbrach oder die Löschung verhinderte, ließ verschlüsselte Daten und Schlüssel an Ort und Stelle: ein Logikfehler in der Reihenfolge der Schritte. Der Fix (AOSP 8b7b2c66, Bug 324321147) ruft vor dem Neustart deleteSecrets() auf, das AndroidKeyStoreMaintenance ausführt. Er ist die Android-Framework-Hälfte des Pixel-Firmware-Fixes, der als .deleteAllKeys()CVE-2024-29748 geführt wird.
Schritt-für-Schritt Angriffsablauf
Eine Löschung wird angefordert
Der Besitzer, eine Geräteadministrator- oder MDM-App oder ein Fernlöschdienst fordert den Werksreset an; er endet in rebootRecoveryWithCommand("--wipe_data ...").
Neustart, ohne etwas zu vernichten
setupOrClearBcb() speichert den Befehl und pm.reboot(REBOOT_RECOVERY) startet das Telefon neu. Die Verschlüsselungsschlüssel sind zu diesem Zeitpunkt unberührt.
Die Löschung wird unterbrochen
Wer das Gerät physisch besitzt, hält den Neustart vor der Recovery an, etwa durch Gedrückthalten von Leiser, um im Bootloader zu landen – die Löschung läuft nie.
Die Daten überstehen den Reset
Die verschlüsselten Nutzerdaten und die Schlüssel, die sie schützen, bleiben auf dem Gerät. Es lässt sich später noch mit Forensik-Werkzeugen angreifen, statt leer zu sein.
Quellcode: Verwundbar vs. Sicher
// services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@Override // Binder call
public void rebootRecoveryWithCommand(String command) {
if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
synchronized (sRequestLock) {
if (!setupOrClearBcb(true, command)) {
return;
}
// BUG: for "--wipe_data" nothing is destroyed yet. The keys that
// protect the user's encrypted data survive until recovery runs the
// wipe. If the reboot is interrupted or the wipe is skipped, the data
// is still recoverable.
PowerManager pm = mInjector.getPowerManager();
pm.reboot(PowerManager.REBOOT_RECOVERY);
}
}
// services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
static final String RECOVERY_WIPE_DATA_COMMAND = "--wipe_data";
@Override // Binder call
public void rebootRecoveryWithCommand(String command) {
if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
boolean isForcedWipe = command != null && command.contains(RECOVERY_WIPE_DATA_COMMAND);
synchronized (sRequestLock) {
if (!setupOrClearBcb(true, command)) {
return;
}
// FIX: destroy the keys first. Deleting every KeyMint key (including
// the synthetic-password protector keys and the keys protecting DE and
// metadata encryption keys) makes FBE data unrecoverable even if the
// wipe in recovery is interrupted or skipped.
if (isForcedWipe) {
deleteSecrets();
}
PowerManager pm = mInjector.getPowerManager();
pm.reboot(PowerManager.REBOOT_RECOVERY);
}
}
private static void deleteSecrets() {
Slogf.w(TAG, "deleteSecrets");
try {
AndroidKeyStoreMaintenance.deleteAllKeys();
} catch (android.security.KeyStoreException e) {
Log.wtf(TAG, "Failed to delete all keys from keystore.", e);
}
}
Checkliste für Engineering & Systemsicherheit
- ✓Geräte auf Android-Sicherheitspatch-Level 2024-09-01 oder neuer halten (Pixel: Juni-2024-Update oder neuer); diese enthalten AOSP 8b7b2c66.
- ✓Bei jeder zerstörenden Löschung zuerst das Schlüsselmaterial vernichten (Crypto-Shredding) und erst danach die langsame Löschung starten, damit eine unterbrochene Löschung nichts Brauchbares hinterlässt.
- ✓Löschabläufe unter Unterbrechung testen – Stromausfall, erzwungener Bootloader-Einstieg, übersprungener Recovery-Schritt – und prüfen, dass sich die Daten danach nicht mehr entschlüsseln lassen.
- ✓In MDM-Abläufen eine Löschung erst als abgeschlossen werten, wenn das Gerät sie bestätigt oder sich sauber neu registriert, und alarmieren, wenn ein gelöschtes Gerät mit altem Zustand wieder auftaucht.
- ✓Auf Geräten mit sensiblen Daten eine starke Displaysperre verlangen, damit verschlüsselte Daten, die eine fehlgeschlagene Löschung überstehen, nicht per Brute Force geknackt werden können.