בדף הזה מפורטות שיטות שונות לוודא שקובץ ה-APK שמותקן במכשיר Android תואם לטענה שהועלתה במודל התובע. התהליך כולל שליפה של ה-APK הרלוונטי מהמכשיר, בדיקה של תקינות הקוד שלו וביצוע הוכחה של הכללה ביומן בפריט המידע שחולץ.
תהליך האימות
יומן שקיפות מיושם באמצעות עץ מרקל שמורכב מגיבובים. צומת עלה מכיל נתונים, וצומת הורה מכיל את הגיבוב של הצמתים הצאצאים שלו.
בעצם, מתבצעים שני חישובים בעץ מרקל כדי לאמת את המאפיין של יומני שקיפות שמוכיח שלא בוצעו שינויים: הוכחת הכללה והוכחת עקביות. הראשון מוכיח שהיומן כולל רשומה שמתאימה לגרסת APK מסוימת. רשומת היומן כוללת גיבוב (hash), שהוא תקציר SHA256 של אסימון חתימת הקוד בפורמט JSON Web Token (JWT), שאפשר לקבל מקובצי APK תואמים. האחרון מוכיח שכאשר מוסיפים רשומות חדשות לעץ, נקודת הבדיקה החדשה עקבית (מבחינה קריפטוגרפית) עם הגרסה הקודמת של העץ.
כדי לאמת קובץ APK מכוסה, מבצעים בדיקת הוכחת הכללה על סמך נקודת ביקורת שנצפתה. שימו לב שאנחנו מתכננים לשלב את היומן הזה עם רשת עדים ציבורית באמצעות פרוטוקול עדים סטנדרטי. כך תקבלו נקודת ביקורת שמאומתת על ידי צד שלישי, שמבטיחה את העקביות של היומן.
אם רוצים לוודא שקובץ ה-APK ששמור במכשיר תואם לטענה שמופיעה במודל של בעל התלונה, אפשר לעיין בתיאור שבהמשך.
הוכחת הכללה
משתמש Android יכול לבדוק אם קובץ APK מכוסה במכשיר שלו נמצא ביומן. לשם כך, הוא צריך קודם לחלץ את קובץ ה-APK ואת המטא-נתונים הרלוונטיים שלו, ואז להשוות את הגיבוב הבסיסי שחושב מחדש לגיבוב הבסיסי שמופיע בנקודת הבדיקה שפורסמה. אם הם זהים, משתמש Android יכול להיות בטוח שחלק מאמצעי ההגנה שמתוארים במודל האיומים פועלים.
איך מאמתים הכללה של קובץ APK ביומן
כמו שצוין קודם, רשימת קובצי ה-APK שכלולים כרגע בתוכנית מופיעה בדף הסקירה הכללית.
דרישות מוקדמות לאימות
לפני שממשיכים לאימות של הארטיפקט (קושחה או APK) בהתאם לתביעה, צריך לוודא שהכלים הבאים זמינים במחשב שמחובר לרשת. יכול להיות שלא תצטרכו את כל השלבים האלה, בהתאם ליעד האימות.
Golang
כלי האימות נכתב ב-Go. כדי לבנות אותו, צריך להתקין את Go 1.24 ואילך מאתר Go.
ממשק הגישור של Android (ADB)
ADB הוא כלי שמתקשר עם מכשיר Android כדי לבדוק את התמונה או לחלץ קובצי APK. הכלי זמין באתר Android SDK Platform Tools.
כלי לאימות הוכחת ההכללה
הכלי לאימות הוכחת ההכללה הוא מודול Go שמבצע שאילתה ביומן השקיפות ומחזיר פלט שמציין אם ארטיפקט כלול ביומן.
הוא מתפרסם במאגר android-binary-transparency GitHub בכתובת
https://github.com/android/android-binary-transparency/tree/main
כדי לשכפל את מאגר avb AOSP:
computer:~$ git clone https://android.googlesource.com/platform/external/avb
כדי לשכפל את מאגר android-binary-transparency ב-GitHub:
computer:~$ git clone https://github.com/android/android-binary-transparency
AAPT2
AAPT2 (Android Asset Packaging Tool) הוא כלי לבנייה שמשמש לקומפילציה ולאריזה של משאבים של אפליקציית Android. הכלי הזה זמין ככלי עצמאי ב-Android SDK Build Tools מגרסה 26.0.2 ואילך.
bundletool
bundletool הוא כלי שמשמש לבניית קובץ Android App Bundle (AAB). אפשר להשתמש בו גם כדי לאמת חתימות של קוד APK.
אפשר להוריד אותו מ-GitHub.
wget או curl
wget ו-curl הם כלים שאפשר להשתמש בהם כדי לאחזר או להוריד קבצים מהאינטרנט. חשוב לוודא שאחד מהכלים האלה מותקן, כי יכול להיות שתסריטי האימות יסתמכו עליהם.
Avbtool
avbtool משמש לחישוב תקציר ה-VBMeta של תמונות המפעל ולאימות של קבצים בינאריים.
אחרי שיבוט המאגר avb (כפי שמוצג בקטע בנושא כלי לאימות הכללה), אפשר למצוא את avbtool.py בספרייה המשובטת avb.
צריך להוסיף את הספרייה הזו למשתנה הסביבה $PATH.
computer:~$ PATH=$PATH:DIRECTORY_CONTAINING_AVBTOOL
Fbpacktool
fbpacktool
הוא סקריפט Python שמשמש לפריקת רכיבים בודדים ב-bootloader.img של Pixel.
אם אתם מאמתים קובצי APK, לא צריך לבצע את הפעולה הזו.
הכלי הזה חשוב כי הוא מאפשר ל-avbtool.py לגלות את התמונות הנדרשות לאימות.
כדי להשתמש בכלי הזה, צריך להוריד את שלושת סקריפטי Python הבאים לספרייה שבה נמצא הקובץ avbtool.py, להגדיר את fbpacktool.py כקובץ הפעלה וליצור קישור סמלי בשם fbpacktool אל fbpacktool.py לנוחותכם.
אם יש לכם 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
אם יש לכם 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 עוזר לבצע פעולות קריפטוגרפיות שונות באמצעות הטרמינל בתהליך האימות. מוודאים שהיא מותקנת במערכת. כדי לבדוק בטרמינל, מריצים את הפקודה הבאה ומוודאים שהתוצאה שמוחזרת לא ריקה:
computer:~$ which openssl
/usr/bin/openssl
יצירת מטען ייעודי (Payload) לאימות
כדי לוודא שקובץ ה-APK שחולץ מהמכשיר תואם לטענות שלנו, צריך ליצור מטען ייעודי (payload) של יומן רישום ממידע שנגזר מקובץ ה-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 הבינארי לפורמט קריא, אנחנו משתמשים בכלי aapt2 שהתקנו קודם (כפי שנדרש בסעיף הדרישות המוקדמות).
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'
מהפלט שלמעלה, אפשר לראות ששם החבילה של ה-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
בעזרת מחרוזת הגיבוב הזו, יש לנו עכשיו את כל המידע שדרוש כדי להרכיב מטען ייעודי (payload) של יומן בהתאם לפורמט שמתואר בקטע 'תוכן היומן'. בדוגמה הזו, מטען ייעודי (payload) של יומן תואם צריך להיראות כך:
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
עכשיו אפשר להשתמש בפקודה bundletool של check-transparency כדי לוודא שחתימת הקוד שמוטמעת בקובץ ה-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 שאתם מאמתים.
אימות הכללת החבילה (הוכחת הכללה)
עכשיו אפשר לבדוק אם החבילה הרלוונטית נכללה ביומן השקיפות, באמצעות מטען הייעודי (payload) שיצרתם קודם.
כלי להוכחת הכללה פורסם ב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_1p_code
המאמת משתמש בנקודת הבדיקה המתאימה ובתוכן היומן (שנמצא בספריית האריחים) כדי לבדוק שמטען ה-APK נמצא ביומן השקיפות, וכך לוודא שהוא אכן פורסם על ידי Google.
הפלט של הפקודה נכתב אל stdout:
-
OK. inclusion check success!אם הקוד של החבילה כלול ביומן, FAILUREאם לא.