
Python-Tool zur Prüfung, ob Android-Verified-Boot-Images (vbmeta) mit öffentlich bekannten Testschlüsseln signiert sind, um Fehlkonfigurationen in Release-Builds zu identifizieren.
Ein Fehler, der NCC-Group-Beratern gelegentlich begegnet, ist das Signieren von Android-Builds mit bekannten privaten Schlüsseln. Dies macht die Gerätehersteller (und damit auch ihre Benutzer) verwundbar, selbst auf Geräten, auf denen Secure Boot aktiviert ist. Dieser Blogbeitrag hat zwei Ziele:
Wenn Android-basierte Geräte hochfahren, wird zunächst überprüft, dass der Bootloader signierten Code ausführt, anschließend verifiziert der Bootloader das High-Level-Betriebssystem (HLOS). Dieser Blogbeitrag behandelt nur den letzteren Teil.
Jeder Chipsatz-Anbieter kann die Root of Trust (RoT) unterschiedlich implementieren, aber typischerweise werden Geräte durch das Konfigurieren von E-Fuses abgesichert. Unveränderlicher ROM-Code, der auf dem Chipsatz gebrannt ist, liest diese E-Fuses und interpretiert sie als Bits eines kryptografischen Hashs. Der Hash wird dann verwendet, um einen vertrauenswürdigen öffentlichen Schlüssel zu verifizieren, der typischerweise in der Bootloader-Binärdatei enthalten ist. Sobald der öffentliche Schlüssel validiert wurde, wird er anschließend verwendet, um kryptografisch zu verifizieren, dass der erste modifizierbare Code, der auf dem Gerät ausgeführt wird, signiert ist. Wenn dieser Prozess korrekt implementiert ist, schlägt jeder Versuch, den Bootloader zu modifizieren, fehl. OEMs, die Android-basierte Geräte herstellen (Überwachungskameras, Smart Plugs oder Sensoren usw.), verwenden in der Regel das Referenzdesign und den Beispielcode des Chipsatz-Anbieters (d. h. Qualcomm) als Ausgangspunkt für ihr Produkt.
AVB ist Teil des Mechanismus, der verwendet wird, um die Integrität der auf einem Gerät ausgeführten Software sicherzustellen. Geräte enthalten eine Partition namens vbmeta, die ein Image enthält, das kryptografisch verifiziert wird. Nachdem der Bootloader eine erfolgreiche Verifizierung durchgeführt hat, vertraut das Gerät dem Inhalt des vbmeta-Images. Das Image enthält Informationen, die der Bootloader anschließend verwendet, um Software auf Partitionen wie boot, vendor oder system zu validieren.
Der Einfachheit halber stellen Chipsatz-Anbieter Referenzcode bereit, der ohne Weiteres erfolgreich kompiliert, um den Device-Bring-up-Prozess des OEMs zu vereinfachen. Anfänglich werden diese Images mit Test-Privatschlüsseln signiert, die ursprünglich von Google erzeugt wurden und in allen Vanilla-Android-Builds vorhanden sind. Manchmal aktualisieren die Chipsatz-Anbieter diese Testschlüssel, aber die privaten Signierschlüssel sind weiterhin im Beispielcode vorhanden und müssen daher als nicht vertrauenswürdig betrachtet werden.
NCC Group hat festgestellt, dass Gerätehersteller den Bootloader zwar korrekt absichern können, indem sie die Fuses konfigurieren, jedoch den standardmäßigen Test-Privatschlüssel, der zum Signieren des HLOS verwendet wird, nicht ändern. Daher könnte ein Angreifer, obwohl der Bootloader nicht modifiziert werden kann, benutzerdefinierten HLOS-Code erstellen und signieren sowie Partitionen aktualisieren, die vom AVB-Prozess erfolgreich verifiziert werden.
NCC Group hat ein Tool erstellt, das prüft, ob vbmeta.img den öffentlichen Teil eines bekannten privaten Schlüssels enthält. Für die Testschlüssel akzeptiert das Tool einen vom Benutzer bereitgestellten Pfad (angegeben durch die Umgebungsvariable BOARD_AVB_KEY_PATH im Android-Build) oder es verwendet eine Sammlung bekannter Schlüssel, die von GitHub gesammelt und mit dem Tool mitgeliefert wurden.
$ 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/'.
Wenn die HLOS-Software mit einem Standard-Privatschlüssel signiert wurde, wird das Problem gemeldet. Zum Beispiel beim LineageOS-Build:
$ 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.
Andernfalls gibt das Tool eine Erfolgsmeldung zurück, siehe zum Beispiel den Pixel9-Build:
$ 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
Android-Entwickler können dieses Tool als schnelle Überprüfung verwenden, um sicherzustellen, dass Builds für Release/Produktion nicht mit öffentlich bekannten privaten Schlüsseln signiert sind. Es könnte auch in den Build-Prozess integriert werden, um sicherzustellen, dass Android-User-Builds korrekt signiert sind, andernfalls schlägt der Build fehl.