flawopen.com/Teardowns/cve-2024-32896-android-factory-reset-wipe-bypass

● CVE-2024-32896 · CVSS 7.8 · उच्च
सुरक्षा अनुसंधान · FlawOpen

CVE-2024-32896: Android फ़ैक्टरी रीसेट को कुंजियाँ नष्ट होने से पहले रोका जा सकता था

CVE-2024-32896 (CVSS 7.8, सीमित और लक्षित हमलों में इस्तेमाल): फ़ैक्टरी रीसेट सिर्फ़ recovery में रीबूट करता था और मिटाने की प्रक्रिया चलने तक एन्क्रिप्शन कुंजियाँ वैसी ही रहती थीं, इसलिए फ़ोन हाथ में रखने वाला व्यक्ति रीबूट रोककर डेटा को वापस पाने लायक बनाए रख सकता था। सुधार रीबूट से पहले Keystore की सभी कुंजियाँ मिटा देता है।

💡 आसान भाषा में (ELI5)

एक कंपनी का नियम है कि खोए हुए लैपटॉप को "श्रेड" का आदेश भेजा जाए। लैपटॉप फिर श्रेडर वाले कमरे की ओर चलता है, जहाँ सारी फ़ाइलें नष्ट होती हैं। लेकिन जिसके हाथ में लैपटॉप है, वह रास्ते में गलियारा रोक सकता है, और फ़ाइलें कहीं नहीं पहुँचतीं, पूरी सुरक्षित रहती हैं। सुधार यह है कि निकलने से पहले लैपटॉप अपनी बंद अलमारी की इकलौती चाबियाँ जला देता है। रास्ते में रोका भी जाए तो कोई उस अलमारी को फिर कभी नहीं खोल सकता।

इस पेज के मुख्य शब्द

फ़ैक्टरी रीसेट (--wipe_data)
उपयोगकर्ता, डिवाइस-एडमिन या MDM ऐप, या रिमोट-वाइप सेवा के कहने पर होने वाला मिटाना। RecoverySystemService.rebootRecoveryWithCommand() recovery के लिए --wipe_data कमांड लिखकर रीबूट करता है।
बूटलोडर कंट्रोल ब्लॉक (BCB)
एक छोटा पार्टिशन (misc) जहाँ Android बूटलोडर और recovery के लिए निर्देश छोड़ता है; इसे setupOrClearBcb() लिखता है।
FBE और सिंथेटिक पासवर्ड
फ़ाइल-आधारित एन्क्रिप्शन। उपयोगकर्ता डेटा की कुंजियाँ एक सिंथेटिक पासवर्ड से बनती हैं, जिसके सुरक्षा ब्लॉब KeyMint कुंजियों से बँधे हैं; उन कुंजियों को नष्ट करने पर डेटा डिक्रिप्ट नहीं हो सकता।
KeyMint / Keystore
हार्डवेयर-समर्थित कुंजी सेवा। AndroidKeyStoreMaintenance.deleteAllKeys() हर KeyMint डिवाइस से अपनी सारी कुंजियाँ मिटाने को कहता है।

मूल कारण विश्लेषण (Root Cause)

RecoverySystemService.java में rebootRecoveryWithCommand() --wipe_data को ऐसे संभालता था: कमांड को बूटलोडर कंट्रोल ब्लॉक में लिखो और रीबूट करो, इस भरोसे पर कि recovery बाद में /data मिटा देगा। जब तक वह मिटाना पूरा न हो, सिंथेटिक पासवर्ड की रक्षा करने वाली KeyMint कुंजियाँ और DE व मेटाडेटा एन्क्रिप्शन कुंजियाँ सुरक्षित रहती थीं। रीबूट रोक देने या मिटाने को चलने न देने पर एन्क्रिप्टेड डेटा और उसकी कुंजियाँ दोनों वहीं रह जाते थे — कामों के क्रम में तार्किक गलती। सुधार (AOSP 8b7b2c66, बग 324321147) रीबूट से पहले deleteSecrets() कॉल करता है, जो AndroidKeyStoreMaintenance.deleteAllKeys() चलाता है। यह CVE-2024-29748 के रूप में दर्ज Pixel फ़र्मवेयर सुधार का Android फ़्रेमवर्क वाला आधा हिस्सा है।

हमले का चरण-दर-चरण प्रवाह

चरण 1

मिटाने का अनुरोध होता है

मालिक, डिवाइस-एडमिन या MDM ऐप, या रिमोट-वाइप सेवा फ़ैक्टरी रीसेट माँगती है, जो अंत में rebootRecoveryWithCommand("--wipe_data ...") तक पहुँचता है।

चरण 2

कुछ नष्ट किए बिना रीबूट

setupOrClearBcb() कमांड सहेजता है और pm.reboot(REBOOT_RECOVERY) फ़ोन रीबूट करता है। इस समय तक एन्क्रिप्शन कुंजियों को छुआ भी नहीं गया है।

चरण 3

मिटाना बीच में रुक जाता है

डिवाइस अपने कब्ज़े में रखने वाला व्यक्ति recovery से पहले ही रीबूट रोक देता है, जैसे वॉल्यूम डाउन दबाए रखकर बूटलोडर में पहुँचना, और मिटाने की प्रक्रिया कभी नहीं चलती।

चरण 4

डेटा रीसेट के बाद भी बचा रहता है

एन्क्रिप्टेड उपयोगकर्ता डेटा और उसकी रक्षा करने वाली कुंजियाँ डिवाइस पर बनी रहती हैं, इसलिए साफ़ होने की जगह उस पर बाद में भी फ़ोरेंसिक टूल से हमला किया जा सकता है।

सोर्स कोड: कमज़ोर बनाम सुरक्षित कार्यान्वयन

कमज़ोर कार्यान्वयन
// 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);
    }
}

इंजीनियरिंग और सिस्टम सुरक्षा चेकलिस्ट

स्रोत