
Un errore che i consulenti di NCC Group incontrano talvolta è firmare i build Android con chiavi private note. Questo rende vulnerabili i produttori di dispositivi (e di conseguenza i loro utenti), anche su dispositivi in cui è abilitato il secure boot. Questo post del blog ha due obiettivi:
Quando i dispositivi basati su Android si avviano, prima viene verificato che il bootloader stia eseguendo codice firmato, poi il bootloader verifica il sistema operativo di alto livello (HLOS). Questo post del blog copre solo quest'ultima parte.
Ogni produttore di chipset può implementare la root of trust (RoT) in modo diverso, ma tipicamente i dispositivi vengono protetti configurando gli e-fuses. Il codice ROM immutabile bruciato sul chipset legge questi e-fuses e li interpreta come bit di un hash crittografico. L'hash viene quindi utilizzato per verificare una chiave pubblica attendibile, tipicamente inclusa nel binario del bootloader. Una volta validata la chiave pubblica, questa viene successivamente usata per verificare crittograficamente che il primo codice modificabile che viene eseguito sul dispositivo sia firmato. Se questo processo è implementato correttamente, qualsiasi tentativo di modificare il bootloader fallirà.
Gli OEM che producono dispositivi basati su Android (telecamere di sorveglianza, smart plug o sensori, ecc.) in genere usano il design di riferimento e il codice di esempio del fornitore del chip (ad esempio Qualcomm) come punto di partenza per il loro prodotto.
AVB fa parte del meccanismo utilizzato per garantire l'integrità del software in esecuzione su un dispositivo. I dispositivi contengono una partizione chiamata vbmeta che contiene un'immagine verificata crittograficamente. Dopo che il bootloader ha effettuato una verifica riuscita, il dispositivo considera attendibile il contenuto dell'immagine vbmeta. L'immagine contiene informazioni che il bootloader usa successivamente per validare il software presente su partizioni come boot, vendor o system.
Per comodità, i fornitori di chipset forniscono codice di riferimento che compila correttamente senza modifiche, per semplificare il processo di bring-up dei dispositivi OEM. Inizialmente, queste immagini vengono firmate usando chiavi private di test, generate originariamente da Google e presenti su tutti i build Android vanilla. A volte i fornitori di chipset aggiornano queste chiavi di test, ma le chiavi private di firma sono ancora presenti nel codice di esempio, quindi devono essere considerate non attendibili.
NCC Group ha scoperto che i produttori di dispositivi possono proteggere correttamente il bootloader configurando i fuse, ma non cambiano la chiave privata di test predefinita usata per firmare l'HLOS. Pertanto, sebbene il bootloader non possa essere modificato, un attaccante potrebbe creare e firmare codice HLOS personalizzato e aggiornare partizioni che verranno verificate con successo dal processo AVB.
NCC Group ha creato uno strumento che verifica se vbmeta.img include la parte pubblica di una chiave privata nota. Per le chiavi di test, lo strumento accetta un percorso fornito dall'utente (indicato dalla variabile d'ambiente BOARD_AVB_KEY_PATH nel build Android), oppure usa una raccolta di chiavi note raccolte da GitHub e incluse nello strumento.
$ python3 test_avb_key.py --help
Usage:
python test_avb_key.py [VBMETA.IMG] [PATH_PRIVATE_KEY]
Parameters:
* Parameter 'VBMETA.IMG' points to a user or userdebug file from an Android build.
Note: the userdebug image fails this test, it is expected.
* Grep Android build for 'BOARD_AVB_KEY_PATH' to obtain path of signing file,
and leave only the path, i.e. 'external/avb/test/data/'.
Se il software HLOS è stato firmato con una chiave privata predefinita, il problema viene segnalato. Ad esempio, per il build LineageOS:
$ python test_avb_key.py ./sample/vbmeta/lineage/vbmeta.img ./sample/aosp/external/avb/test/data/
Opening vbmeta file: ./sample/vbmeta/lineage/vbmeta.img
Using known private key for verification: ./sample/aosp/external/avb/test/data/sign_key.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_atx_pik.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_atx_prk.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_atx_psk.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_atx_puk.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_rsa2048.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_rsa2048_gsi.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_rsa2048_oneplus.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_rsa4096.pem. Public key found at index: 945
If the script was executed on a vbmeta.img file from an Android user build, there is a problem.
In caso contrario, lo strumento restituisce un messaggio di successo; si prenda ad esempio il build Pixel9:
$ python test_avb_key.py ./sample/vbmeta/pixel9/vbmeta.img ./sample/aosp/external/avb/test/data/
Opening vbmeta file: ./sample/vbmeta/pixel9/vbmeta.img
Using known private key for verification: ./sample/aosp/external/avb/test/data/sign_key.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_atx_pik.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_atx_prk.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_atx_psk.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_atx_puk.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_rsa2048.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_rsa2048_gsi.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_rsa2048_oneplus.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_rsa4096.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_rsa4096_oneplus.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_rsa4096_realtek.pem. Public key not found in vbmeta.img file. That's good.
Using known private key for verification: ./sample/aosp/external/avb/test/data/testkey_rsa8192.pem. Public key not found in vbmeta.img file. That's good.
No issues were found with ./sample/vbmeta/pixel9/vbmeta.img
Gli sviluppatori Android possono usare questo strumento come verifica rapida, per assicurarsi che i build per il rilascio/la produzione non siano firmati usando chiavi private pubblicamente note. Potrebbe anche essere integrato nel processo di build per garantire che i build Android di tipo user siano firmati correttamente, altrimenti la build fallirà.