flawopen.com/Teardowns/cve-2024-32896-android-factory-reset-wipe-bypass
CVE-2024-32896: Android फ़ैक्टरी रीसेट को कुंजियाँ नष्ट होने से पहले रोका जा सकता था
CVE-2024-32896 (CVSS 7.8, सीमित और लक्षित हमलों में इस्तेमाल): फ़ैक्टरी रीसेट सिर्फ़ recovery में रीबूट करता था और मिटाने की प्रक्रिया चलने तक एन्क्रिप्शन कुंजियाँ वैसी ही रहती थीं, इसलिए फ़ोन हाथ में रखने वाला व्यक्ति रीबूट रोककर डेटा को वापस पाने लायक बनाए रख सकता था। सुधार रीबूट से पहले Keystore की सभी कुंजियाँ मिटा देता है।
एक कंपनी का नियम है कि खोए हुए लैपटॉप को "श्रेड" का आदेश भेजा जाए। लैपटॉप फिर श्रेडर वाले कमरे की ओर चलता है, जहाँ सारी फ़ाइलें नष्ट होती हैं। लेकिन जिसके हाथ में लैपटॉप है, वह रास्ते में गलियारा रोक सकता है, और फ़ाइलें कहीं नहीं पहुँचतीं, पूरी सुरक्षित रहती हैं। सुधार यह है कि निकलने से पहले लैपटॉप अपनी बंद अलमारी की इकलौती चाबियाँ जला देता है। रास्ते में रोका भी जाए तो कोई उस अलमारी को फिर कभी नहीं खोल सकता।
इस पेज के मुख्य शब्द
फ़ैक्टरी रीसेट (--wipe_data)- उपयोगकर्ता, डिवाइस-एडमिन या MDM ऐप, या रिमोट-वाइप सेवा के कहने पर होने वाला मिटाना।
RecoverySystemServicerecovery के लिए.rebootRecoveryWithCommand()--wipe_dataकमांड लिखकर रीबूट करता है। बूटलोडर कंट्रोल ब्लॉक (BCB)- एक छोटा पार्टिशन (
misc) जहाँ Android बूटलोडर और recovery के लिए निर्देश छोड़ता है; इसेsetupOrClearBcb()लिखता है। FBE और सिंथेटिक पासवर्ड- फ़ाइल-आधारित एन्क्रिप्शन। उपयोगकर्ता डेटा की कुंजियाँ एक सिंथेटिक पासवर्ड से बनती हैं, जिसके सुरक्षा ब्लॉब KeyMint कुंजियों से बँधे हैं; उन कुंजियों को नष्ट करने पर डेटा डिक्रिप्ट नहीं हो सकता।
KeyMint / Keystore- हार्डवेयर-समर्थित कुंजी सेवा।
AndroidKeyStoreMaintenanceहर KeyMint डिवाइस से अपनी सारी कुंजियाँ मिटाने को कहता है।.deleteAllKeys()
मूल कारण विश्लेषण (Root Cause)
RecoverySystemService.java में rebootRecoveryWithCommand() --wipe_data को ऐसे संभालता था: कमांड को बूटलोडर कंट्रोल ब्लॉक में लिखो और रीबूट करो, इस भरोसे पर कि recovery बाद में /data मिटा देगा। जब तक वह मिटाना पूरा न हो, सिंथेटिक पासवर्ड की रक्षा करने वाली KeyMint कुंजियाँ और DE व मेटाडेटा एन्क्रिप्शन कुंजियाँ सुरक्षित रहती थीं। रीबूट रोक देने या मिटाने को चलने न देने पर एन्क्रिप्टेड डेटा और उसकी कुंजियाँ दोनों वहीं रह जाते थे — कामों के क्रम में तार्किक गलती। सुधार (AOSP 8b7b2c66, बग 324321147) रीबूट से पहले deleteSecrets() कॉल करता है, जो AndroidKeyStoreMaintenance चलाता है। यह .deleteAllKeys()CVE-2024-29748 के रूप में दर्ज Pixel फ़र्मवेयर सुधार का Android फ़्रेमवर्क वाला आधा हिस्सा है।
हमले का चरण-दर-चरण प्रवाह
मिटाने का अनुरोध होता है
मालिक, डिवाइस-एडमिन या MDM ऐप, या रिमोट-वाइप सेवा फ़ैक्टरी रीसेट माँगती है, जो अंत में rebootRecoveryWithCommand("--wipe_data ...") तक पहुँचता है।
कुछ नष्ट किए बिना रीबूट
setupOrClearBcb() कमांड सहेजता है और pm.reboot(REBOOT_RECOVERY) फ़ोन रीबूट करता है। इस समय तक एन्क्रिप्शन कुंजियों को छुआ भी नहीं गया है।
मिटाना बीच में रुक जाता है
डिवाइस अपने कब्ज़े में रखने वाला व्यक्ति recovery से पहले ही रीबूट रोक देता है, जैसे वॉल्यूम डाउन दबाए रखकर बूटलोडर में पहुँचना, और मिटाने की प्रक्रिया कभी नहीं चलती।
डेटा रीसेट के बाद भी बचा रहता है
एन्क्रिप्टेड उपयोगकर्ता डेटा और उसकी रक्षा करने वाली कुंजियाँ डिवाइस पर बनी रहती हैं, इसलिए साफ़ होने की जगह उस पर बाद में भी फ़ोरेंसिक टूल से हमला किया जा सकता है।
सोर्स कोड: कमज़ोर बनाम सुरक्षित कार्यान्वयन
// 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);
}
}
इंजीनियरिंग और सिस्टम सुरक्षा चेकलिस्ट
- ✓डिवाइस को Android सिक्योरिटी पैच लेवल 2024-09-01 या उसके बाद पर रखें (Pixel: जून 2024 अपडेट या उसके बाद), जिनमें AOSP 8b7b2c66 शामिल है।
- ✓किसी भी विनाशकारी मिटाने में पहले कुंजी सामग्री नष्ट करें (क्रिप्टो-श्रेडिंग) और उसके बाद ही धीमा मिटाना शुरू करें, ताकि बीच में रुका मिटाना भी कुछ काम का न छोड़े।
- ✓मिटाने की प्रक्रिया को रुकावटों में परखें — बिजली जाना, ज़बरदस्ती बूटलोडर में जाना, recovery चरण छूट जाना — और जाँचें कि उसके बाद डेटा डिक्रिप्ट न हो सके।
- ✓MDM प्रक्रियाओं में मिटाने को तभी पूरा मानें जब डिवाइस पुष्टि करे या साफ़ हालत में दोबारा नामांकित हो, और मिटाया गया डिवाइस पुरानी स्थिति के साथ फिर दिखे तो अलर्ट दें।
- ✓संवेदनशील डेटा वाले डिवाइस पर मज़बूत लॉक-स्क्रीन क्रेडेंशियल अनिवार्य करें, ताकि नाकाम मिटाने के बाद बचे एन्क्रिप्टेड डेटा को ब्रूट-फ़ोर्स से न तोड़ा जा सके।