Quy trình xác minh toàn diện về tính minh bạch của tệp APK Dịch vụ hệ thống của Google

Trang này trình bày các phương thức để đảm bảo rằng APK được cài đặt trên thiết bị Android của bạn tương ứng với thông tin xác nhận quyền sở hữu đã được đưa ra trong Mô hình bên xác nhận quyền sở hữu. Thao tác này bao gồm việc kéo APK có vấn đề ra khỏi thiết bị, kiểm tra tính toàn vẹn của mã và thực hiện quy trình chứng minh việc đưa nhật ký vào đối tượng đã trích xuất.

Quy trình xác minh

Nhật ký minh bạch được triển khai bằng cây Merkle bao gồm các hàm băm. Nút lá chứa dữ liệu và nút mẹ chứa hàm băm của các nút con.

Về cơ bản, hai phép tính được thực hiện trên cây Merkle để xác minh thuộc tính chống giả mạo của nhật ký minh bạch: bằng chứng bao gồm và bằng chứng nhất quán. Cái trước chứng minh rằng nhật ký có một mục tương ứng với một phiên bản APK cụ thể. Mục nhật ký bao gồm một hàm băm, là thuật toán SHA256 của mã thông báo chữ ký mã ở dạng Mã thông báo web JSON (JWT). Bạn có thể lấy mã thông báo này từ các APK tương ứng. Điều này chứng minh rằng khi các mục mới được thêm vào cây, điểm kiểm tra mới sẽ nhất quán (về mặt mật mã) với phiên bản trước của cây.

Để xác minh một APK được bảo vệ, hãy thực hiện kiểm thử bằng chứng bao gồm dựa trên một điểm kiểm tra được chứng kiến. Xin lưu ý rằng chúng tôi dự định tích hợp nhật ký này với một mạng lưới chứng thực công khai bằng cách sử dụng một giao thức chứng thực tiêu chuẩn. Điều này sẽ cung cấp một điểm kiểm tra được chứng kiến, đảm bảo tính nhất quán của nhật ký.

Nếu bạn muốn tự mình kiểm chứng rằng APK bạn có trên thiết bị tuân thủ tuyên bố được đưa ra trong mô hình bên khiếu kiện, hãy tham khảo bài viết dưới đây.

Bằng chứng bao gồm

Người dùng Android có thể kiểm tra xem một APK được đề cập trên thiết bị của họ có nằm trong nhật ký hay không bằng cách trước tiên trích xuất APK và siêu dữ liệu có liên quan, sau đó so sánh hàm băm gốc được tính toán lại với hàm băm gốc có trong điểm kiểm tra đã xuất bản. Nếu các giá trị này khớp nhau, thì người dùng Android có thể yên tâm về một số biện pháp bảo vệ được mô tả trong Mô hình mối đe doạ.

Cách xác minh việc đưa APK vào nhật ký

Như đã mô tả trước đó, bạn có thể tìm thấy danh sách các APK hiện được đề cập trong trang Tổng quan.

Điều kiện tiên quyết để xác minh

Trước khi tiến hành xác minh rằng APK mà bạn vừa trích xuất từ thiết bị của mình tuân thủ yêu cầu của chúng tôi, bạn sẽ cần các công cụ sau bằng cách cài đặt chúng trên một máy tính có kết nối mạng.

Cầu gỡ lỗi Android (ADB)

ADB là một công cụ giao tiếp với thiết bị Android, có trên trang web Công cụ nền tảng SDK Android.

AAPT2

AAPT2 (Công cụ đóng gói tài nguyên Android) là một công cụ bản dựng dùng để biên dịch và đóng gói tài nguyên của một ứng dụng Android. Bạn có thể tìm thấy công cụ này dưới dạng một công cụ độc lập trong Bộ công cụ xây dựng SDK Android phiên bản 26.0.2 trở lên.

bundletool

bundletool là một công cụ dùng để tạo Android App Bundle (AAB). Bạn cũng có thể dùng công cụ này để chuyển đổi AAB thành APK có thể cài đặt trên thiết bị. Bạn có thể tải trình điều khiển này xuống từ GitHub.

Trình xác minh bằng chứng bao gồm

Đây là một mô-đun Go mà chúng tôi đã xuất bản trong một kho lưu trữ git trong Dự án nguồn mở Android (AOSP) có tên là avb. Công cụ này có khả năng truy vấn nhật ký minh bạch về APK Dịch vụ hệ thống của Google và cho biết liệu một gói có được đưa vào nhật ký hay không. Bạn có thể xem ví dụ về cách sử dụng trong phần sau.

Để tải công cụ này xuống, trước tiên, bạn phải sao chép kho lưu trữ avb.

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

Bạn có thể tìm thấy mã nguồn của trình xác minh trong tools/transparency/verify trong kho lưu trữ avb.

Tạo tải trọng để xác minh

Để xác minh rằng APK bạn trích xuất từ thiết bị theo yêu cầu của chúng tôi, bạn phải tạo một tải trọng nhật ký từ thông tin có được từ APK.

Trước khi bắt đầu, hãy đảm bảo rằng bạn có thể sử dụng adb trên thiết bị bằng cách bật tính năng gỡ lỗi adb trên thiết bị.

Sau đó, hãy tìm vị trí cài đặt APK trên thiết bị của bạn. Để phục vụ mục đích của hướng dẫn này, chúng ta sẽ sử dụng APK Android System Key Verifier (com.google.android.contactkeys) làm ví dụ minh hoạ.

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

Nếu APK Trình xác minh khoá hệ thống Android được cài đặt trên thiết bị của bạn, thì lệnh trên sẽ trả về một đường dẫn cho biết vị trí cài đặt APK đó trên thiết bị. Nếu không, bạn sẽ không thấy bất kỳ kết quả nào.

Sau đó, hãy tải APK từ thiết bị Android xuống máy tính mà bạn đang sử dụng lệnh này (lưu ý rằng vị trí thực tế và tên tệp APK trên thiết bị của bạn có thể khác):

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

Để lấy và xác minh tên gói của APK mà bạn vừa tải xuống, trước tiên, bạn cần giải nén APK vì APK là một loại tệp ZIP đặc biệt.

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

Bước này sẽ giải nén tất cả các tệp tạo nên APK. Bạn có thể tìm thấy tên gói và phiên bản trong manifest của APK. Tên gói và phiên bản thường nằm trong một tệp có tên là AndroidManifest.xml.

Tuy nhiên, tệp kê khai thu được ở dạng nhị phân, không phải dạng người dùng có thể đọc được. Để chuyển đổi XML nhị phân thành dạng người dùng có thể đọc được, chúng ta sẽ sử dụng công cụ aapt2 đã cài đặt trước đó (theo yêu cầu phải cài đặt trong phần điều kiện tiên quyết).

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'

Từ đầu ra ở trên, giờ đây, chúng ta có thể chắc chắn rằng tên gói của APK này là com.google.android.contactkeys và số phiên bản (versionCode) là 1413.

Bây giờ, chúng ta sẽ tìm chữ ký minh bạch của mã trong APK. Đây phải là một tệp có tên là code_transparency_signed.jwt nằm trong thư mục META-INF cùng với các tệp khác được trích xuất từ APK.

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

Với chuỗi băm này, chúng ta hiện có mọi thông tin cần thiết để ghép nối một tải trọng nhật ký theo định dạng được mô tả trong phần Nội dung nhật ký. Trong ví dụ này, một tải trọng nhật ký tương ứng sẽ có dạng như sau:

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

Ngoài ra, hãy lưu ý ký tự dòng mới sau phiên bản gói.

Bạn có thể lưu nội dung vào một tệp, chẳng hạn như payload.txt. Điều này sẽ hữu ích khi bạn thực hiện kiểm thử bằng chứng bao gồm sau này.

Xác minh tính xác thực của chữ ký mã APK

Giờ đây, chúng ta cần xác minh tính xác thực của mã thông báo chữ ký mã được nhúng trong APK. Để làm việc này, chúng ta sử dụng bundletool và khoá công khai của cặp khoá đã được dùng để ký khoá đó ngay từ đầu. Chúng được xuất bản trong từng phần của các APK tương ứng. Giả sử bạn đã lưu chứng chỉ khoá công khai (ví dụ: cho Trình xác minh khoá hệ thống Android) vào một tệp có tên là signing_cert_pubkey.pem, hãy làm theo hướng dẫn bên dưới để thực hiện quy trình xác minh chữ ký mã.

Trước tiên, bạn nên tạo một tệp lưu trữ zip rồi thêm APK đề xuất vào tệp lưu trữ 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

Bây giờ, chúng ta đã sẵn sàng sử dụng lệnh check-transparency của bundletool để xác minh xem chữ ký mã được nhúng trong APK đề xuất có khớp với chữ ký đã xuất bản hay không.

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.

Bạn nên đảm bảo rằng đầu ra của lệnh trên cho biết cả chữ ký minh bạch của mãtính minh bạch của mã đều được xác minh. Nếu không, ví dụ: nếu bạn thấy đầu ra như Code transparency verification failed because the provided public key certificate does not match the transparency file, điều này có nghĩa là tính toàn vẹn của mã trong APK có vấn đề có thể bị xâm phạm và bạn không nên tin tưởng APK đó. Hãy nhớ kiểm tra kỹ để đảm bảo bạn đang xác minh chúng bằng chứng chỉ khoá công khai chính xác. Nếu mọi thứ khác đều ổn, thì điều này có nghĩa là tính xác thực của chữ ký mã đã được xác minh cho APK mà bạn đang xác thực.

Xác minh việc đưa gói vào (Bằng chứng về việc đưa gói vào)

Bằng cách sử dụng tải trọng mà bạn đã tạo trước đó, giờ đây, bạn đã sẵn sàng kiểm tra xem gói có liên quan đã được đưa vào nhật ký minh bạch hay chưa.

Một công cụ chứng minh việc đưa vào đã được xuất bản trong avb kho lưu trữ trong Dự án nguồn mở Android. Cách chạy:

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

Trình xác minh sử dụng điểm kiểm tra tương ứng và nội dung nhật ký (có trong thư mục ô) để kiểm tra xem tải trọng APK của bạn có nằm trong nhật ký minh bạch hay không, xác minh rằng tải trọng đó thực sự do Google xuất bản.

Đầu ra của lệnh được ghi vào stdout:

  • OK. inclusion check success! nếu mã của gói có trong nhật ký,
  • FAILURE nếu không.