Vollständige Überprüfung der APK-Transparenz von Google-Systemdiensten

Auf dieser Seite werden verschiedene Methoden beschrieben, mit denen Sie sicherstellen können, dass das auf Ihrem Android-Gerät installierte APK dem Anspruch entspricht, der im Modell des Anspruchstellers erhoben wurde. Dazu wird das betreffende APK von Ihrem Gerät abgerufen, seine Code-Integrität geprüft und ein Log-Inclusion-Nachweis für das extrahierte Artefakt erbracht.

Bestätigungsverfahren

Ein Transparenzprotokoll wird mit einem Merkle-Baum implementiert, der aus Hashes besteht. Ein Blattknoten enthält Daten und ein übergeordneter Knoten den Hash seiner untergeordneten Knoten.

Grundsätzlich werden zwei Berechnungen am Merkle-Baum durchgeführt, um die Manipulationssicherheit von Transparenzlogs zu überprüfen: der Einschlussbeweis und der Konsistenzbeweis. Ersteres beweist, dass das Log einen Eintrag für eine bestimmte APK-Version enthält. Der Logeintrag enthält einen Hash, der der SHA256-Digest des Codesignatur-Tokens in Form eines JSON Web Token (JWT) ist. Dieser kann aus entsprechenden APKs abgerufen werden. Letzteres beweist, dass der neue Prüfpunkt (kryptografisch) mit der vorherigen Version des Baums übereinstimmt, wenn dem Baum neue Einträge hinzugefügt werden.

Um eine abgedeckte APK zu bestätigen, führen Sie einen Einschlussnachweistest auf Grundlage eines bezeugten Prüfpunkts durch. Wir planen, dieses Log in ein öffentliches Zeugennetzwerk zu integrieren, das ein standardisiertes Zeugenprotokoll verwendet. Dadurch wird ein bezeugter Prüfpunkt bereitgestellt, der die Konsistenz des Logs garantiert.

Wenn Sie sich selbst davon überzeugen möchten, dass das APK auf Ihrem Gerät dem Anspruch im Modell des Anspruchstellers entspricht, lesen Sie den folgenden Text.

Nachweis der Aufnahme

Ein Android-Nutzer kann prüfen, ob ein abgedecktes APK auf seinem Gerät im Log enthalten ist. Dazu muss er zuerst das APK und die zugehörigen Metadaten extrahieren und dann den neu berechneten Stamm-Hash mit dem Stamm-Hash im veröffentlichten Prüfpunkt vergleichen. Wenn sie übereinstimmen, kann sich der Android-Nutzer auf einige der im Bedrohungsmodell beschriebenen Schutzmaßnahmen verlassen.

So prüfen Sie, ob ein APK im Log enthalten ist

Wie bereits beschrieben, finden Sie die Liste der derzeit abgedeckten APKs auf der Übersichtsseite.

Voraussetzungen für die Bestätigung

Bevor Sie überprüfen können, ob die APK, die Sie gerade von Ihrem Gerät extrahiert haben, unserem Anspruch entspricht, benötigen Sie die folgenden Tools. Installieren Sie sie auf einem Computer, der mit dem Netzwerk verbunden ist.

Android Debug Bridge (ADB)

ADB ist ein Tool, das mit einem Android-Gerät kommuniziert und auf der Website der Android SDK Platform Tools verfügbar ist.

AAPT2

AAPT2 (Android Asset Packaging Tool) ist ein Build-Tool, das zum Kompilieren und Verpacken der Ressourcen einer Android-App verwendet wird. Es ist als eigenständiges Tool in den Android SDK Build Tools ab Version 26.0.2 verfügbar.

bundletool

bundletool ist ein Tool zum Erstellen eines Android App Bundles (AAB). Es kann auch verwendet werden, um ein AAB in APKs zu konvertieren, die auf Geräten installiert werden können. Sie können es von GitHub herunterladen.

Inclusion Proof-Prüfung

Dies ist ein Go-Modul, das wir in einem Git-Repository im Android Open Source Project (AOSP) mit dem Namen avb veröffentlicht haben. Es kann das Transparenz-Log für Google-Systemdienste-APKs abfragen und ausgeben, ob ein Paket im Log enthalten ist. Ein Beispiel für die Verwendung finden Sie weiter unten.

Um dieses Tool herunterzuladen, müssen Sie zuerst das avb-Repository klonen.

computer:~$ git clone https://android.googlesource.com/platform/external/avb

Der Quellcode des Prüftools befindet sich im Repository avb unter tools/transparency/verify.

Nutzlast für die Bestätigung erstellen

Um zu überprüfen, ob das APK, das Sie gemäß unseren Behauptungen von Ihrem Gerät extrahiert haben, mit dem APK übereinstimmt, das wir für Ihr Gerät generiert haben, müssen Sie eine Log-Nutzlast aus Informationen erstellen, die aus dem APK abgeleitet wurden.

Prüfen Sie zuerst, ob adb auf Ihrem Gerät verwendet werden kann, indem Sie ADB-Debugging auf Ihrem Gerät aktivieren.

Suchen Sie dann auf Ihrem Gerät nach dem Speicherort der APK. In diesem Leitfaden verwenden wir die APK Android System Key Verifier (com.google.android.contactkeys) als Arbeitsbeispiel.

computer:~$ adb shell pm list packages -f | grep contactkeys
package:/data/app/~~i5WYSO4PuAAv798-eHdM7A==/com.google.android.contactkeys-PQCKjnn7xDqjeVhcUDibBA==/base.apk=com.google.android.contactkeys

Wenn die APK für den Android System Key Verifier auf Ihrem Gerät installiert ist, gibt der oben genannte Befehl einen Pfad zurück, der angibt, wo sie auf Ihrem Gerät installiert ist. Andernfalls wird keine Ausgabe angezeigt.

Laden Sie dann die APK-Datei von Ihrem Android-Gerät auf den Computer herunter, den Sie verwenden. Verwenden Sie dazu diesen Befehl (beachten Sie, dass der tatsächliche Speicherort und der APK-Dateiname auf Ihrem Gerät variieren können):

computer:~$ mkdir -p /tmp/testdir && cd /tmp/testdir
computer:/tmp/testdir$ adb pull /data/app/~~i5WYSO4PuAAv798-eHdM7A==/com.google.android.contactkeys-PQCKjnn7xDqjeVhcUDibBA==/base.apk ./contactkeys_candidate.apk

Um den Paketnamen der gerade heruntergeladenen APK-Datei zu erhalten und somit zu überprüfen, müssen Sie die APK-Datei zuerst entpacken, da eine APK-Datei letztendlich eine spezielle Art von ZIP-Datei ist.

computer:/tmp/testdir$ mkdir extracted && unzip contactkeys_candidate.apk -d extracted/

In diesem Schritt werden alle Dateien entpackt, aus denen das APK besteht. Der Paketname und die Version sind im Manifest des APK zu finden, das sich normalerweise in einer Datei mit dem Namen AndroidManifest.xml befindet.

Die erhaltene Manifestdatei ist jedoch binär und daher nicht menschenlesbar. Um das binäre XML in ein für Menschen lesbares Format zu konvertieren, verwenden wir das zuvor installierte Tool aapt2 (wie im Abschnitt Voraussetzung erforderlich).

computer:/tmp/testdir$ aapt2 dump badging ./contactkeys_candidate.apk
package: name='com.google.android.contactkeys' versionCode='7805' versionName='1.219.791156583' platformBuildVersionName='Baklava' platformBuildVersionCode='36' compileSdkVersion='36' compileSdkVersionCodename='Baklava'

Anhand der obigen Ausgabe können wir sicher sein, dass der Paketname dieses APKs com.google.android.contactkeys und die Versionsnummer (versionCode) 1413 ist.

Als Nächstes suchen wir in der APK nach der Signatur für Codetransparenz. Es sollte sich um eine Datei mit dem Namen code_transparency_signed.jwt handeln, die sich im Ordner META-INF zwischen den anderen aus der APK extrahierten Dateien befindet.

computer:/tmp/testdir$ sha256sum extracted/META-INF/code_transparency_signed.jwt
1779a2aee029112c2c9bfc9390b9678f3e5f4595b39705e8528dd522e8042f11  code_transparency_signed.jwt

Mit diesem Hash-String haben wir nun alle Informationen, die wir benötigen, um eine Log-Nutzlast gemäß dem im Abschnitt „Log-Inhalt“ beschriebenen Format zusammenzustellen. In diesem Beispiel sollte eine entsprechende Log-Nutzlast so aussehen:

1779a2aee029112c2c9bfc9390b9678f3e5f4595b39705e8528dd522e8042f11
SHA256(Signed Code Transparency JWT)
com.google.android.contactkeys
1143

Beachten Sie auch das Zeilenumbruchzeichen nach der Paketversion.

Sie können den Inhalt in einer Datei speichern, z. B. payload.txt. Das ist später beim Testen des Einschlusses hilfreich.

Authentizität der APK-Codesignatur prüfen

Als Nächstes sollten wir die Authentizität des in das APK eingebetteten Codesignatur-Tokens überprüfen. Dazu verwenden wir bundletool und den öffentlichen Schlüssel des Schlüsselpaars, mit dem es ursprünglich signiert wurde. Sie werden in jedem Abschnitt der jeweiligen APKs veröffentlicht. Angenommen, Sie haben das Zertifikat für den öffentlichen Schlüssel (z. B. für Android System Key Verifier) in einer Datei mit dem Namen signing_cert_pubkey.pem gespeichert. Folgen Sie der Anleitung unten, um die Codesignatur zu überprüfen.

Erstellen Sie zuerst ein ZIP-Archiv und fügen Sie die Kandidaten-APK in das ZIP-Archiv ein.

computer:/tmp/testdir$ zip -u test.zip contactkeys_candidate.apk
        zip warning: test.zip not found or empty
  adding: contactkeys_candidate.apk (deflated 58%)

computer:/tmp/testdir$ file test.zip
test.zip: Zip archive data, at least v2.0 to extract, compression method=deflate

Wir können jetzt den check-transparency-Befehl von bundletool verwenden, um zu prüfen, ob die in die Kandidaten-APK eingebettete Codesignatur mit der veröffentlichten Signatur übereinstimmt.

computer:/tmp/testdir$ java -jar BUNDLETOOL_INSTALL_PATH/bundletool-all-version.jar check-transparency \
  --mode=apk \
  --apk-zip=test.zip \
  --transparency-key-certificate=signing_cert_pubkey.pem

APK signature is valid. SHA-256 fingerprint of the apk signing key certificate (must be compared with the developer's public key manually): D9 E1 73 5B 2A 39 51 27 3A 87 35 B7 66 9E F1 9E F5 3A F1 C1 27 5C BA 31 39 3C 18 40 8B 03 79 D0
Code transparency signature verified for the provided code transparency key certificate.
Code transparency verified: code related file contents match the code transparency file.

Die Ausgabe des obigen Befehls sollte bestätigen, dass sowohl die Signatur für Codetransparenz als auch die Codetransparenz überprüft wurden. Wenn dies nicht der Fall ist, z. B. wenn Sie eine Ausgabe wie Code transparency verification failed because the provided public key certificate does not match the transparency file sehen, bedeutet das, dass die Code-Integrität des betreffenden APK möglicherweise beeinträchtigt wurde. Sie sollten dem APK nicht vertrauen. Achten Sie darauf, dass Sie die Signaturen mit dem richtigen Zertifikat für den öffentlichen Schlüssel überprüfen. Andernfalls, wenn alles andere in Ordnung ist, bedeutet dies, dass die Authentizität der Codesignatur für die APK, die Sie validieren, bestätigt wurde.

Paketaufnahme bestätigen (Aufnahmenachweis)

Mit der zuvor erstellten Nutzlast können Sie nun testen, ob das betreffende Paket im Transparenzlog enthalten ist.

Im avb-Repository des Open-Source-Projekts für Android wurde ein Tool zum Nachweis der Aufnahme veröffentlicht. So führen Sie es aus:

computer:external/avb/tools/transparency/verify$ PAYLOAD_PATH=PATH_TO_PAYLOAD_DIR/payload.txt
computer:external/avb/tools/transparency/verify$ go build cmd/verifier/verifier.go
computer:external/avb/tools/transparency/verify$ ./verifier --payload_path=${PAYLOAD_PATH} --log_type=google_system_apk

Der Prüfer verwendet den entsprechenden Prüfpunkt und den Log-Inhalt (im Kachelverzeichnis), um zu prüfen, ob sich die APK-Nutzlast im Transparenzlog befindet. So wird bestätigt, dass sie tatsächlich von Google veröffentlicht wurde.

Die Ausgabe des Befehls wird in stdout geschrieben:

  • OK. inclusion check success!, wenn der Code des Pakets im Log enthalten ist.
  • FAILURE, wenn das nicht der Fall ist.