flawopen.com/Teardowns/cve-2024-32896-android-factory-reset-wipe-bypass
CVE-2024-32896: a redefinição de fábrica do Android podia ser interrompida antes de as chaves serem destruídas
CVE-2024-32896 (CVSS 7.8, explorada em ataques limitados e direcionados): a redefinição de fábrica apenas reiniciava no modo recovery e deixava as chaves de criptografia intactas até o apagamento rodar, então quem estivesse com o celular podia interromper a reinicialização e manter os dados recuperáveis. A correção apaga todas as chaves do Keystore antes de reiniciar.
A regra de uma empresa para notebook perdido é mandar a ordem "triturar". O notebook então segue até a sala do triturador, onde todos os arquivos são destruídos. Mas quem está segurando o notebook pode bloquear o corredor no caminho, e os arquivos não chegam a lugar nenhum e continuam intactos. A correção é que, antes de sair, o notebook queima as únicas chaves do seu arquivo trancado. Mesmo que o caminho seja interrompido, ninguém nunca mais consegue abrir o arquivo.
Conceitos Centrais e Termos
Redefinição de fábrica (--wipe_data)- Apagamento pedido pelo usuário, por um app de administrador do dispositivo ou MDM, ou por um serviço de apagamento remoto.
RecoverySystemServicegrava o comando.rebootRecoveryWithCommand()--wipe_datapara o recovery e reinicia. Bloco de controle do bootloader (BCB)- Pequena partição (
misc) onde o Android deixa instruções para o bootloader e o recovery, gravada porsetupOrClearBcb(). FBE e a senha sintética- Criptografia baseada em arquivos. As chaves dos dados do usuário derivam de uma senha sintética cujos blobs protetores estão presos a chaves do KeyMint; destruir essas chaves torna os dados indecifráveis.
KeyMint / Keystore- Serviço de chaves com suporte de hardware.
AndroidKeyStoreMaintenancepede a cada dispositivo KeyMint que apague todas as suas chaves..deleteAllKeys()
Análise de Causa Raiz
rebootRecoveryWithCommand() em RecoverySystemService.java tratava --wipe_data gravando o comando no bloco de controle do bootloader e reiniciando, confiando que o recovery apagaria /data depois. Até esse apagamento terminar, as chaves do KeyMint que protegem a senha sintética e as chaves de criptografia DE e de metadados continuavam intactas. Interromper a reinicialização, ou impedir que o apagamento rodasse, deixava os dados criptografados e suas chaves no lugar: um erro de lógica na ordem das operações. A correção (AOSP 8b7b2c66, bug 324321147) chama deleteSecrets(), que executa AndroidKeyStoreMaintenance, antes da reinicialização. É a metade do framework Android da correção de firmware do Pixel registrada como .deleteAllKeys()CVE-2024-29748.
Fluxo de Ataque Passo a Paso
Um apagamento é solicitado
O dono, um app de administrador do dispositivo ou MDM, ou um serviço de apagamento remoto pede a redefinição de fábrica, que termina em rebootRecoveryWithCommand("--wipe_data ...").
Reinício sem destruir nada
setupOrClearBcb() guarda o comando e pm.reboot(REBOOT_RECOVERY) reinicia o celular. Nesse ponto as chaves de criptografia não foram tocadas.
O apagamento é interrompido
Alguém com posse física interrompe a reinicialização antes do recovery, por exemplo segurando o botão de diminuir volume para cair no bootloader, e o apagamento nunca roda.
Os dados sobrevivem à redefinição
Os dados criptografados do usuário e as chaves que os protegem continuam no aparelho, que ainda pode ser atacado depois com ferramentas forenses em vez de estar limpo.
Código-Fonte: Vulnerável vs. Seguro
// 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);
}
}
Lista de Verificação de Segurança para Engenharia
- ✓Mantenha os aparelhos no nível de patch de segurança do Android 2024-09-01 ou posterior (Pixel: atualização de junho de 2024 ou posterior), que incluem o AOSP 8b7b2c66.
- ✓Em qualquer apagamento destrutivo, destrua primeiro o material de chave (crypto-shredding) e só depois comece o apagamento lento, para que um apagamento interrompido não deixe nada utilizável.
- ✓Teste os fluxos de apagamento sob interrupção — queda de energia, entrada forçada no bootloader e etapa de recovery pulada — e verifique que os dados não podem mais ser decifrados depois.
- ✓Nos procedimentos de MDM, considere um apagamento concluído só quando o aparelho confirmar ou se reinscrever limpo, e gere alerta quando um aparelho apagado reaparecer com o estado antigo.
- ✓Em aparelhos com dados sensíveis, exija uma credencial de tela de bloqueio forte, para que dados criptografados que sobrevivam a uma falha de apagamento não possam ser quebrados por força bruta.