Verificación completa de transparencia del APK de los servicios del sistema de Google

En esta página, se describen varios métodos para garantizar que el APK instalado en tu dispositivo Android corresponda al reclamo que se realizó en el Modelo del solicitante. Esto implica extraer el APK en cuestión de tu dispositivo, verificar su integridad de código y realizar una prueba de inclusión de registro en el artefacto extraído.

Proceso de verificación

Un registro de transparencia se implementa con un árbol Merkle que consta de hashes. Un nodo hoja contiene datos, y un nodo superior contiene el hash de sus elementos secundarios.

Básicamente, se realizan dos cálculos en el árbol de Merkle para verificar la propiedad de inviolabilidad de los registros de transparencia: la prueba de inclusión y la prueba de coherencia. El primero demuestra que el registro incluye una entrada correspondiente a una versión de APK en particular. La entrada de registro incluye un hash, que es el resumen SHA256 del token de firma de código en forma de token web JSON (JWT), que se puede obtener de los APKs correspondientes. Esto último demuestra que, cuando se agregan entradas nuevas al árbol, el nuevo punto de control es (criptográficamente) coherente con la versión anterior del árbol.

Para verificar un APK cubierto, realiza una prueba de prueba de inclusión basada en un punto de control presenciado. Ten en cuenta que planeamos integrar este registro con una red de testigos pública con un protocolo de testigo estandarizado. Esto proporcionará un punto de control testigo, que garantiza la coherencia del registro.

Si quieres asegurarte de que el APK que tienes en tu dispositivo cumpla con el reclamo que se hace en el modelo del solicitante, consulta el siguiente documento.

Prueba de inclusión

Un usuario de Android puede verificar que un APK cubierto en su dispositivo esté en el registro. Para ello, primero debe extraer el APK y sus metadatos relevantes y, luego, comparar el hash raíz recalculado con el hash raíz contenido en el punto de control publicado. Si coinciden, el usuario de Android puede estar seguro de algunas protecciones que se describen en el modelo de amenazas.

Cómo verificar la inclusión de un APK en el registro

Como se describió anteriormente, la lista de APKs que se incluyen actualmente se puede encontrar en la página Descripción general.

Requisitos previos para la verificación

Antes de continuar con la verificación de que el APK que acabas de extraer de tu dispositivo cumpla con nuestro reclamo, necesitarás las siguientes herramientas, que deberás instalar desde una computadora conectada a una red.

Android Debug Bridge (ADB)

ADB es una herramienta que se comunica con un dispositivo Android y está disponible en el sitio web de las herramientas de la plataforma del SDK de Android.

bundletool

bundletool es una herramienta que se usa para compilar un Android App Bundle (AAB). También se puede usar para convertir un AAB en APKs que se pueden instalar en dispositivos. Se puede descargar desde GitHub.

Androguard

Androguard es un conjunto de herramientas que se usa para analizar APKs. Se puede descargar e instalar desde el sitio web de Androguard.

Verificador de pruebas de inclusión

Este es un módulo Go que publicamos en un repositorio de git dentro del Proyecto de código abierto de Android (AOSP) llamado avb. Puede consultar el registro de transparencia del APK de los servicios del sistema de Google y mostrar si se incluye un paquete en el registro. Puedes encontrar un ejemplo de cómo se usa en una sección posterior.

Para descargar esta herramienta, primero debes clonar el repositorio avb.

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

El código fuente del verificador se puede encontrar en tools/transparency/verify dentro del repositorio avb.

Cómo crear una carga útil para la verificación

Para verificar que el APK que extrajiste de tu dispositivo según nuestras afirmaciones, debes crear una carga útil de registro a partir de la información derivada del APK.

Antes de comenzar, asegúrate de que se pueda usar adb en tu dispositivo. Para ello, habilita la depuración de adb en él.

Luego, busca dónde está instalado el APK en tu dispositivo. A los efectos de esta guía, usaremos el APK de Android System Key Verifier (com.google.android.contactkeys) como ejemplo de trabajo.

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 el APK de Android System Key Verifier está instalado en tu dispositivo, el comando anterior mostrará una ruta de acceso que indica dónde está instalado en tu dispositivo. De lo contrario, no verás ningún resultado.

Luego, descarga el APK de tu dispositivo Android a la computadora en la que estás trabajando con este comando (ten en cuenta que la ubicación real y el nombre del archivo APK en tu dispositivo pueden variar):

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

Para obtener y verificar el nombre del paquete del APK que acabas de descargar, primero deberás descomprimirlo, ya que, en última instancia, un APK es un tipo especial de archivo ZIP.

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

En este paso, se descomprimen todos los archivos que conforman el APK. El nombre y la versión del paquete se pueden encontrar en el manifiesto del APK, que suele estar en un archivo llamado AndroidManifest.xml.

Sin embargo, el archivo de manifiesto obtenido está en formato binario, que no es legible por humanos. Para convertir el XML binario en un formato legible por humanos, usamos la herramienta axml del paquete androguard (como se requiere para instalar en la sección requisito previo).

computer:/tmp/testdir$ androguard axml extracted/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1413" android:versionName="1.48.688082145" android:compileSdkVersion="35" android:compileSdkVersionCodename="VanillaIceCream" android:requiredSplitTypes="" android:splitTypes="" package="com.google.android.contactkeys" platformBuildVersionCode="35" platformBuildVersionName="VanillaIceCream">

A partir del resultado anterior, ahora podemos asegurarnos de que el nombre del paquete de este APK es com.google.android.contactkeys y el número de versión (versionCode) es 1413.

Ahora, buscaremos la firma de transparencia de código dentro del APK. Debe ser un archivo llamado code_transparency_signed.jwt contenido en la carpeta META-INF entre los otros archivos extraídos del APK.

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

Con esta cadena de hash, ahora tenemos toda la información necesaria para armar una carga útil de registro según el formato que se describe en la sección Contenido de registro. En este ejemplo, una carga útil de registro correspondiente debería verse de la siguiente manera:

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

Observa también el carácter de línea nueva después de la versión del paquete.

Puedes guardar el contenido en un archivo, como payload.txt. Esto te será útil cuando realices la prueba de prueba de inclusión más adelante.

Verifica la autenticidad de la firma de código del APK

Ahora, debemos verificar la autenticidad del token de firma de código incorporado en el APK. Para ello, usamos bundletool y la clave pública del par de claves que se usó para firmarlo en primer lugar. Se publican en cada sección de los respectivos APKs. Si suponemos que guardaste el certificado de clave pública (p.ej., para el verificador de claves del sistema Android) en un archivo llamado signing_cert_pubkey.pem, sigue la guía que aparece a continuación para realizar la verificación de la firma de código.

Primero, debes crear un archivo ZIP y agregar el APK candidato al archivo ZIP.

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

Ahora tenemos todo listo para usar el comando check-transparency de bundletool para verificar si la firma de código incorporada en el APK candidato coincide con la que se publicó.

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.

Debes asegurarte de que el resultado del comando anterior indique que se verificaron la firma de transparencia de código y la transparencia de código. De lo contrario, por ejemplo, si ves resultados como Code transparency verification failed because the provided public key certificate does not match the transparency file, significa que la integridad del código del APK en cuestión podría estar comprometida y que no debes confiar en el APK. Recuerda verificar que los estés comparando con el certificado de clave pública correcto. De lo contrario, si todo está bien, significa que se verifica la autenticidad de la firma del código del APK que estás validando.

Verificación de la inclusión de paquetes (prueba de inclusión)

Con la carga útil que compilaste anteriormente, ya puedes probar si el paquete en cuestión se incluyó en el registro de transparencia.

Se publicó una herramienta de prueba de inclusión en el repositorio avb dentro del Proyecto de código abierto de Android. Para ejecutarlo, haz lo siguiente:

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

El verificador usa el punto de control correspondiente y el contenido del registro (que se encuentra en el directorio de tarjetas) para verificar que la carga útil de tu APK esté en el registro de transparencia y que Google la haya publicado.

El resultado del comando se escribe en stdout:

  • OK. inclusion check success! si el código del paquete se incluye en el registro
  • FAILURE si no lo es.