אימות מלא של שקיפות חבילות APK בשירותי המערכת של Google

בדף הזה מפורטות שיטות שונות להבטיח שה-APK שמותקן במכשיר Android תואם לטענה שהוגשה במודל של המתלונן. התהליך כולל אחזור של חבילת ה-APK הרלוונטית מהמכשיר, בדיקה של תקינות הקוד שלה וביצוע הוכחת הכללה ביומן של הארטיפקט שחולץ.

תהליך האימות

יומן שקיפות מיושם באמצעות עץ Merkle שמורכב מ-hashes. צומת עלה מכיל נתונים, וצומת הורה מכיל את הגיבוב של הצאצאים שלו.

בעיקרון, מתבצעים שני חישובים בעץ Merkle כדי לאמת את המאפיין של יומני השקיפות, שמבטיח שהם לא ניתנים לזיוף: הוכחת ההכללה והוכחת העקביות. הקוד הראשון מוכיח שהיומן כולל רשומה שתואמת לגרסה מסוימת של APK. הרשומה ביומן כוללת גיבוב, שהוא סיכום SHA256 של אסימון החתימה על הקוד, בפורמט של אסימון אינטרנט מסוג JSON‏ (JWT). אפשר לקבל את האסימון הזה מקובצי ה-APK התואמים. הבדיקה האחרונה מוכיחה שכאשר מוסיפים רשומות חדשות לעץ, נקודת הבדיקה החדשה תואמת (קריפטוגרפית) לגרסה הקודמת של העץ.

כדי לאמת קובץ APK מכוסה, מבצעים בדיקת הוכחת הכללה על סמך נקודת בקרה שנצפתה. חשוב לדעת שאנחנו מתכננים לשלב את היומן הזה עם רשת ציבורית של עדי ראייה באמצעות פרוטוקול סטנדרטי של עדים. כך תקבלו נקודת ניהול מאומתת, שתבטיח את העקביות של היומן.

כדי לוודא שה-APK במכשיר שלך תואם לטענה שמופיעה במודל של המתלונן, אפשר לעיין במאמר שבהמשך.

הוכחת ההכללה

משתמש Android יכול לבדוק אם קובץ APK מכוסה במכשיר שלו נמצא ביומן. לשם כך, קודם צריך לחלץ את קובץ ה-APK ואת המטא-נתונים הרלוונטיים שלו, ואז להשוות את גיבוב הבסיס (root hash) שחושב מחדש לבין גיבוב הבסיס שמופיע בנקודת הבדיקה שפורסמה. אם הם תואמים, משתמשי Android יכולים להיות בטוחים שהם מוגנים באמצעות חלק מהאמצעי שמפורטים במודל האיום.

איך מוודאים ש-APK כלול ביומן

כפי שמתואר למעלה, רשימת חבילות ה-APK שנכללות כרגע בתוכנית מופיעה בדף הסקירה הכללית.

דרישות מוקדמות לאימות

לפני שתמשיך ותבדוק שה-APK שחולץ מהמכשיר שלך תואם לטענה שלנו, עליך להתקין את הכלים הבאים במחשב שמחובר לרשת.

Android Debug Bridge‏ (ADB)

ADB הוא כלי שמאפשר תקשורת עם מכשיר Android, והוא זמין באתר של Android SDK Platform Tools.

כלי Bundletool

bundletool הוא כלי שמשמש ליצירת קובץ Android App Bundle ‏ (AAB). אפשר גם להשתמש בו כדי להמיר קובץ AAB לקובצי APK שאפשר להתקין במכשירים. אפשר להוריד אותו מ-GitHub.

Androguard

Androguard הוא אוסף כלים לניתוח חבילות APK. אפשר להוריד ולהתקין אותו מאתר Androguard.

מאמת הוכחת הכללה

זהו מודול Go שפרסמנו במאגר git בפרויקט קוד פתוח של Android‏ (AOSP) בשם avb. הוא יכול להריץ שאילתות ביומן השקיפות של חבילות ה-APK בשירותי המערכת של Google, ולהציג את הפלט של חבילה כלשהי שכלולה ביומן. דוגמה לשימוש באפשרות הזו מופיעה בקטע מאוחר יותר.

כדי להוריד את הכלי הזה, קודם צריך לשכפל את המאגר avb.

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

קוד המקור של המאמת נמצא ב-tools/transparency/verify במאגר avb.

יצירה של עומס נתונים לאימות

כדי לאמת את קובץ ה-APK שחולץ מהמכשיר בהתאם לטענות שלנו, צריך ליצור עומס נתונים ביומן מידע שמבוסס על קובץ ה-APK.

לפני שמתחילים, צריך לוודא שאפשר להשתמש ב-adb במכשיר. לשם כך, מפעילים את ניפוי הבאגים של adb במכשיר.

לאחר מכן, מאתרים את מיקום קובץ ה-APK במכשיר. במדריך הזה נשתמש בקובץ ה-APK של Android System Key Verifier (com.google.android.contactkeys) כדוגמה לעבודה.

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

אם קובץ ה-APK של הכלי לאימות מפתחות של מערכת Android מותקן במכשיר, הפקודה שלמעלה תחזיר נתיב שמציין את המיקום שבו הוא מותקן במכשיר. אחרת, לא יופיע פלט.

לאחר מכן, מורידים את קובץ ה-APK ממכשיר Android למחשב שבו אתם עובדים באמצעות הפקודה הבאה (שימו לב שהמיקום בפועל ושם קובץ ה-APK במכשיר עשויים להשתנות):

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

כדי לקבל ולאמת את שם החבילה של קובץ ה-APK שהורדתם, קודם תצטרכו לפתוח את קובץ ה-APK, כי בסופו של דבר קובץ APK הוא סוג מיוחד של קובץ ZIP.

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

בשלב הזה מתבצעת פריקת האריזה של כל הקבצים שמרכיבים את קובץ ה-APK. שם החבילה והגרסה מופיעים במניפסט של קובץ ה-APK, שנמצא בדרך כלל בקובץ בשם AndroidManifest.xml.

עם זאת, קובץ המניפסט שהתקבל הוא בפורמט בינארי, שלא ניתן לקריאה על ידי בני אדם. כדי להמיר את ה-XML הבינארי לפורמט קריא לבני אדם, אנחנו משתמשים בכלי axml מחבילת androguard (כפי שנדרש להתקנה בקטע דרישות מוקדמות).

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">

לפי הפלט שלמעלה, עכשיו אנחנו יכולים להיות בטוחים ששם החבילה של קובץ ה-APK הזה הוא com.google.android.contactkeys ומספר הגרסה (versionCode) הוא 1413.

עכשיו נבצע חיפוש של החתימה על שקיפות הקוד בתוך קובץ ה-APK. זה אמור להיות קובץ בשם code_transparency_signed.jwt שנמצא בתיקייה META-INF בין הקבצים האחרים שחולצו מה-APK.

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

באמצעות מחרוזת הגיבוב הזו, יש לנו עכשיו את כל פרטי המידע הנדרשים כדי להרכיב עומס נתונים ביומן בהתאם לפורמט שמתואר בקטע 'תוכן היומן'. בדוגמה הזו, המטען הייעודי התואם של היומן אמור להיראות כך:

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

שימו לב גם לתו של שורת חדשה אחרי גרסת החבילה.

אפשר לשמור את התוכן בקובץ, למשל payload.txt. זה יעזור לכם מאוחר יותר כשתבצעו את הבדיקה של הוכחת ההכללה.

אימות האותנטיות של חתימה על קוד APK

עכשיו עלינו לאמת את האותנטיות של אסימון חתימת הקוד שמוטמע ב-APK. לשם כך, אנחנו משתמשים ב-bundletool ובמפתח הציבורי של זוג המפתחות ששימש לחתימה עליו מלכתחילה. הם מתפרסמים בכל קטע של קובצי ה-APK הרלוונטיים. נניח ששמרתם את האישור של המפתח הציבורי (למשל, של Android System Key Verifier) בקובץ בשם signing_cert_pubkey.pem. כדי לבצע אימות של חתימת הקוד, פועלים לפי המדריך שבהמשך.

קודם צריך ליצור קובץ ארכיון zip ולהוסיף את קובץ ה-APK של המועמד לקובץ הארכיון.

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

עכשיו אנחנו מוכנים להשתמש בפקודה check-transparency של bundletool כדי לוודא שחתימת הקוד שמוטמעת בקובץ ה-APK של המועמד תואמת לחתימה שפורסמה.

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.

צריך לוודא שבפלט של הפקודה שלמעלה מצוין שגם חותמת השקיפות של הקוד וגם השקיפות של הקוד מאומתים. אם לא, למשל, אם מופיע פלט כמו Code transparency verification failed because the provided public key certificate does not match the transparency file, המשמעות היא שיכול להיות ששלמות הקוד של קובץ ה-APK המדובר נפגמה, ולא כדאי לסמוך על קובץ ה-APK. חשוב לבדוק שוב שאתם מבצעים את האימות באמצעות אישור המפתח הציבורי הנכון. אם כל שאר הנתונים תקינים, סימן שהאותנטיות של חתימת הקוד אומתה עבור קובץ ה-APK שאתם מאמתים.

אימות ההכללה בחבילה (הוכחת הכללה)

עכשיו, בעזרת עומס העבודה שיצרתם לפני כן, אתם מוכנים לבדוק אם החבילה הרלוונטית נכללה ביומן השקיפות.

פורסם כלי להוכחת הכללה במאגר avb בפרויקט הקוד הפתוח של Android. כדי להריץ אותו:

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

המאמת משתמש בנקודת הבקרה המתאימה ובתוכן היומן (שנמצא בספריית המשבצות) כדי לבדוק שהמטען הייעודי של קובץ ה-APK נמצא ביומן השקיפות, וכך לוודא שהוא אכן פורסם על ידי Google.

הפלט של הפקודה נכתב ל-stdout:

  • OK. inclusion check success! אם הקוד של החבילה נכלל ביומן,
  • FAILURE אם הוא לא מופיע.