Vérification complète de la transparence des APK des services système Google

Cette page décrit différentes méthodes permettant de s'assurer que l'APK installé sur votre appareil Android correspond à l'affirmation faite dans le modèle de demandeur. Cela implique d'extraire l'APK en question de votre appareil, de vérifier l'intégrité de son code et d'effectuer une preuve d'inclusion du journal sur l'artefact extrait.

Processus de vérification

Un journal de transparence est implémenté avec un arbre de Merkle constitué de hachages. Un nœud feuille contient des données, et un nœud parent contient le hachage de ses enfants.

En gros, deux calculs sont effectués sur l'arbre de Merkle pour vérifier la propriété d'inviolabilité des journaux de transparence : la preuve d'inclusion et la preuve de cohérence. La première prouve que le journal inclut une entrée correspondant à une version d'APK particulière. L'entrée de journal inclut un hachage, qui est le condensé SHA256 du jeton de signature de code sous la forme d'un jeton Web JSON (JWT), qui peut être obtenu à partir des APK correspondants. La seconde prouve que lorsque de nouvelles entrées sont ajoutées à l'arbre, le nouveau point de contrôle est (cryptographiquement) cohérent avec la version précédente de l'arbre.

Pour vérifier un APK couvert, effectuez un test de preuve d'inclusion basé sur un point de contrôle observé. Notez que nous prévoyons d'intégrer ce journal à un réseau de témoins public à l'aide d'un protocole de témoin standardisé . Cela fournira un point de contrôle observé, ce qui garantira la cohérence du journal.

Si vous souhaitez vous assurer que l'APK dont vous disposez sur votre appareil est conforme à l'affirmation faite dans le modèle de demandeur, consultez le texte ci-dessous.

Preuve d'inclusion

Un utilisateur Android peut vérifier qu'un APK couvert sur son appareil se trouve dans le journal en extrayant d'abord l'APK et ses métadonnées pertinentes, puis en comparant le hachage racine recalculé avec le hachage racine contenu dans le point de contrôle publié. S'ils correspondent, l'utilisateur Android peut être assuré de certaines protections décrites dans le modèle de menace.

Comment vérifier l'inclusion d'un APK dans un journal

Comme indiqué précédemment, la liste des APK actuellement couverts se trouve listée sur la page Présentation.

Conditions préalables pour la validation

Avant de vérifier que l'artefact (micrologiciel ou APK) est conforme à l'affirmation, assurez-vous que les outils suivants sont disponibles sur un ordinateur connecté au réseau. Selon la cible de vérification, vous n'aurez peut-être pas besoin de tous ces outils.

Golang

L'outil de vérification est écrit en Go. Pour le compiler, installez Go 1.24 ou version ultérieure à partir du site Go.

Android Debug Bridge (ADB)

ADB est un outil qui communique avec un appareil Android pour inspecter l'image ou extraire des APK. Il est disponible sur le site Web Android SDK Platform Tools website.

Outil de vérification de la preuve d'inclusion

L'outil de vérification de la preuve d'inclusion est un module Go qui interroge le journal de transparence et indique si un artefact est inclus dans le journal. Il est publié dans le dépôt GitHub android-binary-transparency à l'adresse https://github.com/android/android-binary-transparency/tree/main.

Pour cloner le dépôt AOSP avb :

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

Pour cloner le dépôt GitHub android-binary-transparency :

computer:~$ git clone https://github.com/android/android-binary-transparency

AAPT2

AAPT2 (Android Asset Packaging Tool) est un outil de compilation utilisé pour compiler et empaqueter les ressources d'une application Android. Il est disponible en tant qu'outil autonome dans les outils de compilation du SDK Android version 26.0.2 et versions ultérieures.

bundletool

bundletool est un outil utilisé pour créer un Android App Bundle (AAB). Il peut également être utilisé pour vérifier les signatures de code APK. Il peut être téléchargé depuis GitHub.

wget ou curl

wget et curl sont des outils qui peuvent être utilisés pour récupérer ou télécharger des fichiers depuis Internet. Assurez-vous que l'un de ces outils est installé, car les scripts de vérification peuvent en dépendre.

Avbtool

avbtool est utilisé pour calculer le condensé VBMeta des images d'usine et la vérification des binaires. Après avoir cloné le dépôt avb (comme indiqué dans la section Outil de vérification de la preuve d'inclusion ), avbtool.py se trouve dans le répertoire avb cloné. Vous devez ajouter ce répertoire à votre variable d'environnement $PATH.

computer:~$ PATH=$PATH:DIRECTORY_CONTAINING_AVBTOOL

Fbpacktool

fbpacktool est un script Python utilisé pour décompresser des composants individuels dans Pixel's bootloader.img. Vous n'en avez pas besoin si vous vérifiez des APK. Cet outil est important, car il permet à avbtool.py de découvrir les images requises pour la vérification.

Pour utiliser cet outil, vous devez télécharger les trois scripts Python suivants dans le répertoire où se trouve votre avbtool.py, rendre fbpacktool.py exécutable, et créer un lien symbolique nommé fbpacktool vers fbpacktool.py pour plus de commodité.

Si vous disposez de wget :

computer:dir_to_avbtool$ wget https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/fbpacktool.py \
https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/fbpack.py \
https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/packedstruct.py
computer:dir_to_avbtool$ chmod +x fbpacktool.py
computer:dir_to_avbtool$ ln -s fbpacktool.py fbpacktool

Si vous disposez de curl :

computer:dir_to_avbtool$ curl -O https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/fbpacktool.py
computer:dir_to_avbtool$ curl -O https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/fbpack.py
computer:dir_to_avbtool$ curl -O https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/packedstruct.py
computer:dir_to_avbtool$ chmod +x fbpacktool.py
computer:dir_to_avbtool$ ln -s fbpacktool.py fbpacktool

OpenSSL

openssl permet d'effectuer diverses opérations cryptographiques à l'aide du terminal dans le workflow de vérification. Assurez-vous qu'il est installé sur votre système. Vous pouvez vérifier sur votre terminal en exécutant la commande suivante et en vous assurant que le résultat renvoyé n'est pas vide :

computer:~$ which openssl
/usr/bin/openssl

Créer une charge utile pour la vérification

Pour vérifier que l'APK que vous avez extrait de votre appareil conformément à nos affirmations, vous devez créer une charge utile de journal à partir des informations dérivées de l'APK.

Avant de commencer, assurez-vous que adb peut être utilisé sur votre appareil en activant le débogage adb sur votre appareil.

Ensuite, recherchez l'emplacement où l'APK est installé sur votre appareil. Pour les besoins de ce guide, nous utiliserons l'APK Android System Key Verifier (com.google.android.contactkeys) comme exemple de travail.

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

Si l'APK Android System Key Verifier est installé sur votre appareil, la commande ci-dessus renvoie un chemin indiquant où il est installé sur votre appareil. Sinon, aucun résultat ne s'affiche.

Ensuite, téléchargez l'APK depuis votre appareil Android sur l'ordinateur sur lequel vous travaillez à l'aide de cette commande (notez que l'emplacement réel et le nom de fichier APK sur votre appareil peuvent varier) :

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

Pour obtenir et donc vérifier le nom de package de l'APK que vous venez de télécharger, vous devez d'abord décompresser l'APK, car un APK est en fin de compte un type spécial de fichier ZIP.

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

Cette étape décompresse tous les fichiers qui composent l'APK. Le nom et la version du package se trouvent dans le manifeste de l'APK, qui se trouve généralement dans un fichier nommé AndroidManifest.xml.

Toutefois, le fichier manifeste obtenu est au format binaire, qui n'est pas lisible par l'homme. Pour convertir le XML binaire en un format lisible par l'homme, nous faisons usage de l'outil aapt2 installé précédemment (comme requis dans la section Conditions préalables).

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'

À partir du résultat ci-dessus, nous pouvons maintenant être sûrs que le nom de package de cet APK est com.google.android.contactkeys et que le numéro de version (versionCode) est 1413.

Nous allons maintenant rechercher la signature de transparence du code dans l'APK. Il doit s'agir d'un fichier nommé code_transparency_signed.jwt contenu dans le dossier META-INF parmi les autres fichiers extraits de l'APK.

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

Avec cette chaîne de hachage, nous disposons désormais de toutes les informations nécessaires pour assembler une charge utile de journal au format décrit dans la section Contenu du journal. Dans cet exemple, une charge utile de journal correspondante doit se présenter comme suit :

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

Notez également le caractère de nouvelle ligne après la version du package.

Vous pouvez enregistrer le contenu dans un fichier, tel que payload.txt. Cela sera utile lors du test de preuve d'inclusion ultérieur.

Vérifier l'authenticité de la signature de code APK

Nous devons maintenant vérifier l'authenticité du jeton de signature de code intégré à l'APK. Pour ce faire, nous utilisons bundletool et la clé publique de la paire de clés qui a été utilisée pour la signer en premier lieu. Ils sont publiés dans chaque section des APK respectifs. En supposant que vous ayez enregistré le certificat de clé publique (par exemple, pour Android System Key Verifier) dans un fichier nommé signing_cert_pubkey.pem, suivez le guide ci-dessous pour effectuer la vérification de la signature de code.

Vous devez d'abord créer une archive ZIP et y ajouter l'APK candidat.

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

Nous sommes maintenant prêts à utiliser la commande check-transparency de bundletool pour vérifier si la signature de code intégrée à l'APK candidat correspond à celle qui est publiée.

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.

Vous devez vous assurer que le résultat de la commande ci-dessus indique que la signature de transparence du code et la transparence du code sont vérifiées. Si ce n'est pas le cas, par exemple si vous voyez un résultat tel que Code transparency verification failed because the provided public key certificate does not match the transparency file, cela signifie que l'intégrité du code de l'APK en question peut être compromise et que vous ne devez pas faire confiance à l'APK. N'oubliez pas de vérifier que vous les comparez au bon certificat de clé publique. Sinon, si tout le reste est vérifié, cela signifie que l'authenticité de la signature de code est vérifiée pour l'APK que vous validez.

Vérifier l'inclusion du package (preuve d'inclusion)

À l'aide de la charge utile que vous avez créée précédemment, vous êtes maintenant prêt à vérifier si le package en question a été inclus dans le journal de transparence.

Un outil de preuve d'inclusion a été publié dans le avb dépôt au sein du projet Android Open Source. Pour l'exécuter :

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_1p_code

L'outil de vérification utilise le point de contrôle correspondant et le contenu du journal (situé dans le répertoire de la vignette) pour vérifier que la charge utile de votre APK se trouve dans le journal de transparence, en vérifiant qu'elle est bien publiée par Google.

Le résultat de la commande est écrit dans stdout :

  • OK. inclusion check success! si le code du package est inclus dans le journal,
  • FAILURE si ce n'est pas le cas.