Pełna weryfikacja przejrzystości aplikacji usługi Google

Na tej stronie opisujemy, jak sprawdzić, czy plik APK lub APEX zainstalowany na urządzeniu z Androidem odpowiada informacjom podanym w modelu zgłaszającego. Proces ten obejmuje pobranie pliku APK z urządzenia i przeprowadzenie weryfikacji włączenia do dziennika na wyodrębnionym artefakcie.

Proces weryfikacji

Dziennik przejrzystości jest implementowany za pomocą drzewa Merkle składającego się z haszy. Węzeł liścia zawiera dane, a węzeł nadrzędny zawiera hasz swoich węzłów podrzędnych.

Dwa podstawowe obliczenia weryfikują właściwość dzienników przejrzystości, która polega na tym, że nie można ich modyfikować bez pozostawienia śladu: weryfikacja włączenia i weryfikacja spójności. Weryfikacja włączenia potwierdza, że dziennik zawiera wpis dotyczący konkretnej wersji pliku APK. Ten wpis logu zawiera hasz, który jest skrótem SHA256 pliku APK zainstalowanego na urządzeniu. Weryfikacja spójności zapewnia, że po dodaniu nowych wpisów nowy punkt kontrolny pozostaje kryptograficznie spójny z poprzednimi wersjami drzewa (lub że drzewo nie zostało zmodyfikowane). W tym przewodniku skupiamy się na procesie obliczania weryfikacji włączenia, a jednocześnie korzystamy z świadków, którzy na bieżąco przeprowadzają weryfikację spójności w odniesieniu do najnowszych punktów kontrolnych.

Aby zweryfikować objęty plik APK, przeprowadź weryfikację włączenia w odniesieniu do punktu kontrolnego potwierdzonego przez świadka. Planujemy zintegrować ten dziennik z publiczną siecią świadków za pomocą standardowego protokołu świadka. Ta integracja zapewni punkty kontrolne potwierdzone przez świadków, co zagwarantuje spójność dziennika.

Aby sprawdzić, czy aplikacje Google na Twoim urządzeniu są zgodne z informacjami podanymi w modelu zgłaszającego, wykonaj te czynności.

Weryfikacja włączenia

Możesz sprawdzić, czy objęty plik APK na Twoim urządzeniu znajduje się w dzienniku, wyodrębniając go, obliczając jego hasz i używając weryfikacji włączenia, aby sprawdzić, czy ten hasz istnieje w opublikowanym punkcie kontrolnym. Pomyślna weryfikacja włączenia zapewnia ochronę przed zagrożeniami opisanymi w modelu zagrożeń, potwierdzając, że aplikacja jest legalną aplikacją Google.

Jak sprawdzić, czy plik APK jest uwzględniony w dzienniku

Każda aplikacja, która twierdzi, że jest aplikacją Google, może zostać zweryfikowana na podstawie tego dziennika.

Weryfikacja – wymagania wstępne

Zanim przejdziesz do weryfikacji, czy artefakt (oprogramowanie układowe lub plik APK) jest zgodny z deklaracją, upewnij się, że na komputerze połączonym z siecią są dostępne te narzędzia. W zależności od celu weryfikacji możesz nie potrzebować wszystkich tych narzędzi.

Golang

Narzędzie do weryfikacji jest napisane w języku Go. Aby je skompilować, zainstaluj Go w wersji 1.24 lub nowszej ze strony Go.

Android Debug Bridge (ADB)

ADB to narzędzie, które komunikuje się z urządzeniem z Androidem, aby sprawdzić obraz lub wyodrębnić pliki APK. Jest dostępne na stronie Android SDK Platform Tools website.

Weryfikator weryfikacji włączenia

Weryfikator weryfikacji włączenia to moduł Go, który wysyła zapytania do dziennika przejrzystości i informuje, czy artefakt jest uwzględniony w dzienniku. Jest on opublikowany w repozytorium GitHub android-binary-transparency pod adresem https://github.com/android/android-binary-transparency/tree/main.

Aby sklonować repozytorium AOSP avb:

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

Aby sklonować repozytorium GitHub android-binary-transparency:

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

AAPT2

AAPT2 (Android Asset Packaging Tool) to narzędzie do kompilacji służące do kompilowania i pakowania zasobów aplikacji na Androida. Można je znaleźć jako samodzielne narzędzie w Android SDK Build Tools w wersji 26.0.2 i nowszej.

bundletool

bundletool to narzędzie służące do tworzenia pakietów Android App Bundle (AAB). Może też służyć do weryfikowania podpisów kodu APK. Można je pobrać z GitHub.

wget lub curl

wget i curl to narzędzia, których można używać do pobierania plików z internetu. Upewnij się, że masz zainstalowane jedno z tych narzędzi, ponieważ skrypty weryfikacyjne mogą z nich korzystać.

Avbtool

avbtool służy do obliczania skrótu VBMeta obrazów fabrycznych i weryfikacji plików binarnych. Po sklonowaniu repozytorium avb (jak pokazano w sekcji Weryfikator weryfikacji włączenia ) plik avbtool.py można znaleźć w sklonowanym katalogu avb. Ten katalog należy dodać do zmiennej środowiskowej $PATH.

computer:~$ PATH=$PATH:DIRECTORY_CONTAINING_AVBTOOL

Fbpacktool

fbpacktool to skrypt w Pythonie służący do rozpakowywania poszczególnych komponentów w Pixel's bootloader.img. Nie jest to potrzebne, jeśli weryfikujesz pliki APK. To narzędzie jest ważne, ponieważ umożliwia avbtool.py wykrywanie obrazów wymaganych do weryfikacji.

fbpacktool wymaga Pythona w wersji 3.6 lub nowszej oraz pakietu PyYAML (na przykład python3 -m pip install pyyaml).

Aby korzystać z tego narzędzia, pobierz te 6 skryptów w Pythonie do katalogu, w którym znajduje się avbtool.py, ustaw fbpacktool.py jako wykonywalny, i utwórz link symboliczny o nazwie fbpacktool do fbpacktool.py.

Jeśli masz wget:

computer:dir_to_avbtool$ wget https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/fbpacktool.py \
https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/fbpack.py \
https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/packedstruct.py \
https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/xmlparser.py \
https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/xmlserializer.py \
https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/yamlparser.py
computer:dir_to_avbtool$ chmod +x fbpacktool.py
computer:dir_to_avbtool$ ln -s fbpacktool.py fbpacktool

Jeśli masz curl:

computer:dir_to_avbtool$ curl -LO https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/fbpacktool.py
computer:dir_to_avbtool$ curl -LO https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/fbpack.py
computer:dir_to_avbtool$ curl -LO https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/packedstruct.py
computer:dir_to_avbtool$ curl -LO https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/xmlparser.py
computer:dir_to_avbtool$ curl -LO https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/xmlserializer.py
computer:dir_to_avbtool$ curl -LO https://developers.google.com/android/binary_transparency/tools/pixel/fbpacktool/yamlparser.py
computer:dir_to_avbtool$ chmod +x fbpacktool.py
computer:dir_to_avbtool$ ln -s fbpacktool.py fbpacktool

OpenSSL

openssl pomaga wykonywać różne operacje kryptograficzne za pomocą terminala w procesie weryfikacji. Upewnij się, że jest zainstalowany w systemie. Możesz to sprawdzić w terminalu, uruchamiając to polecenie i upewniając się, że zwrócony wynik nie jest pusty:

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

Tworzenie ładunku do weryfikacji

Aby zweryfikować wyodrębniony plik APK, musisz utworzyć ładunek dziennika, używając informacji pochodzących z samego pliku APK.

Zanim zaczniesz, włącz debugowanie USB na urządzeniu, aby zezwolić na adb połączenia.

Następnie znajdź zainstalowany plik APK na urządzeniu. W tym przewodniku jako przykład używamy pliku APK usług Google Play (com.google.android.gms).

adb shell pm path com.google.android.gms

Zostaną wyświetlone dane wyjściowe podobne do tych:

computer:~$ adb shell pm path com.google.android.gms
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/base.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_CronetDynamite_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_DynamiteLoader_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_DynamiteModulesA_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_DynamiteModulesC_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_GoogleCertificates_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_MapsDynamite_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_MeasurementDynamite_installtime.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_config.en.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_config.xxhdpi.apk
package:/data/app/~~oI3N-m7I3VNMk5eKUCscQg==/com.google.android.gms-O79jYXgqkqKaQ9IzJ5zqfA==/split_maps_core_dynamite_ondemand.apk

Te dane wyjściowe wskazują, że na urządzeniu zainstalowano 1 podstawowy plik APK i kilka dzielonych pakietów APK zainstalowano dla com.google.android.gms. Dokładna liczba dzielonych pakietów APK zależy od konfiguracji urządzenia. Każdy dzielony pakiet APK ma taką samą nazwę pakietu i kod wersji jak podstawowy pakiet APK.

Pobierz wymienione pliki APK z urządzenia z Androidem na komputer za pomocą tego polecenia (pamiętaj, że rzeczywiste ścieżki plików mogą się różnić):

mkdir -p /tmp/testdir/gms && cd /tmp/testdir/gms && \
adb shell pm path com.google.android.gms | cut -d':' -f2 | tr -d '\r' | xargs -n1 adb pull

Aby sprawdzić nazwę pakietu i wersję pobranych plików APK, musisz sprawdzić ich manifest (AndroidManifest.xml).

Ponieważ manifest w pliku APK jest w formacie binarnym, użyj narzędzia aapt2(zainstalowanego w kroku wymagań wstępnych), aby wyodrębnić i odczytać informacje bezpośrednio z pliku APK:

computer:/tmp/testdir/gms$ aapt2 dump badging ./base.apk
package: name='com.google.android.gms' versionCode='260834035' versionName='26.08.34 (260400-876566425)' platformBuildVersionName='Baklava' platformBuildVersionCode='36' compileSdkVersion='36' compileSdkVersionCodename='Baklava'
minSdkVersion:'35'
targetSdkVersion:'36'
...

Powtórz ten krok, aby uzyskać odpowiednie informacje, aż uwzględnisz wszystkie podzielone pliki APK zainstalowane na urządzeniu.

Dane wyjściowe potwierdzają, że nazwa pakietu APK to com.google.android.gms, a jego numer wersji (versionCode) to 260834035.

Następnie oblicz hasz kryptograficzny każdego pliku APK:

computer:/tmp/testdir/gms$ sha256sum *.apk
66aa2d7b9752cdd61065b55c8e16739d8367fa18a0f1c8c84122369f86958f1a  base.apk
c20754aee886cc55a9de91ee15c623c59d94ad22b7e435a1a48afc43cf1a106c  split_config.en.apk
68c09b63a1262e0d34020c139bc77deff3c32bd2b01177abac64790a62fb3be6  split_config.xxhdpi.apk
cd746820c27babd855fa5daea6fabcdf7b44abf3060bc547adc4219212410af0  split_CronetDynamite_installtime.apk
512ee48b60fdb0787a17f84a7dc448fdbf885b2b86a9cb50525d4c22d561b0f1  split_DynamiteLoader_installtime.apk
9e0c74bdc75c50c80d4e2e580a7eda6b8391423ab1161645f41ec6cadc07d678  split_DynamiteModulesA_installtime.apk
955780ac01f59b98bd9be12968f3824ad71b762620f7bf223c569c1a6ab7056c  split_DynamiteModulesC_installtime.apk
34c4a2e32d31554d55fc1519e2cfc3ed5027a090fb29b54cfc99f42d1da43bc5  split_GoogleCertificates_installtime.apk
475e18dde92472cde9d8300c082b6dc269613db03398bcd9d1987dff3e68f7b5  split_maps_core_dynamite_ondemand.apk
f83faf40f08bc13f4879302e01c08c863ca2304b4b4e7c9eaf8cd1e869bb6573  split_MapsDynamite_installtime.apk
ec6d854ddda6cd1ba2ba7af2d9fdf4f28c5c78be8713c64521c785429296738c  split_MeasurementDynamite_installtime.apk

Masz teraz wszystkie informacje potrzebne do utworzenia ładunku dziennika w formacie opisanym w sekcji Zawartość dziennika. Wybierając jako przykład 1 hasz z wyników (należy zweryfikować hasz każdego dzielonego pakietu APK), ładunek dziennika wygląda tak:

66aa2d7b9752cdd61065b55c8e16739d8367fa18a0f1c8c84122369f86958f1a
SHA256(APK)
com.google.android.gms
260834035

Upewnij się, że na końcu pliku znajduje się znak nowego wiersza. Zapisz tę zawartość w pliku, np. payload.txt, aby później użyć jej z narzędziem verifier.

Weryfikowanie włączenia pakietu (weryfikacja włączenia)

Po utworzeniu ładunku możesz sprawdzić, czy pakiet jest uwzględniony w dzienniku przejrzystości. Skompiluj narzędzie do weryfikacji włączenia z repozytorium android-binary-transparency, które zostało wcześniej sklonowane:

go build cmd/verifier/verifier.go

Powinno to spowodować utworzenie w tym katalogu pliku wykonywalnego o nazwie verifier. Uruchom weryfikator, podając ścieżkę do ładunku i określając typ dziennika:

computer:android-binary-transparency$ PAYLOAD_PATH=PATH_TO_PAYLOAD_DIR/payload.txt
computer:android-binary-transparency$ ./verifier --payload_path=${PAYLOAD_PATH} --log_type=google_1p_apk

Weryfikator używa punktu kontrolnego i zawartości dziennika (z katalogu tile) aby sprawdzić, czy ładunek APK znajduje się w dzienniku przejrzystości, potwierdzając, że został opublikowany przez Google.

Wynik polecenia jest wyświetlany w stderr:

  • OK. inclusion check success! (OK. Weryfikacja włączenia zakończona pomyślnie), jeśli pakiet jest uwzględniony w dzienniku.
  • FAILURE (NIEPOWODZENIE), jeśli nie jest.

Automatyczne weryfikowanie wszystkich pakietów na urządzeniu

Ze względu na liczbę aplikacji Google, które mogą być fabrycznie zainstalowane na urządzeniu, wyliczanie każdej aplikacji i przeprowadzanie weryfikacji włączenia osobno może być żmudne.

Udostępniamy inne zautomatyzowane narzędzie o nazwie Uraniborg, które może wykrywać i mierzyć wszystkie aktualnie zainstalowane pakiety na urządzeniu. Przesyła ono dane wyjściowe bezpośrednio do narzędzia verifier, co pozwala w jednym kroku wykryć i zweryfikować przejrzystość wszystkich aplikacji na urządzeniu.

Aby korzystać z tego zautomatyzowanego procesu, upewnij się, że urządzenie z Androidem jest połączone z komputerem za pomocą ADB. Kod źródłowy Uraniborg jest też zawarty w repozytorium android-binary-transparency.

Uruchom skrypt automate_observation.py znajdujący się w katalogu scripts/python:

python3 automate_observation.py --pull-all-apks --perform_inclusion_proof_check --verifier_path <path_to_verifier_executable>

Po zakończeniu skryptu powinny się wyświetlić dane wyjściowe podobne do tych:

INFO:automate_observation.py:main(858): SUCCESS! Hubble was successfully deployed and executed on connected device ABCDEFGHN01234.
INFO:automate_observation.py:main(860): Hubble output files can be found at: /Users/user/home/src/android-binary-transparency/uraniborg/scripts/python/results/google/lynx/lynx:16/BP4A.260105.004.E1/14587043:user/release-keys/001

Przejdź do katalogu wyjściowego wskazanego przez skrypt. Znajdź w nim plik o nazwie packages_with_inclusion_proof_signal.txt. Ten plik zawiera listę każdego zainstalowanego pakietu wraz z polem inclusion_proof_verified ustawionym na true lub false. Wartość true oznacza, że pakiet został kryptograficznie zweryfikowany na podstawie dziennika przejrzystości, co potwierdza, że jest zgodny z informacjami w dzienniku.