Play Integrity API là gì? Cách chặn app bị crack, chạy trên máy giả lập và cài từ nguồn ngoài

2026-08-08 15 phút đọc 1 lượt xemBởi Uwmee Software

Bạn đầu tư nhiều tháng xây một ứng dụng có gói trả phí, rồi một ngày phát hiện bản mod của chính app mình đang được phát tán trên các diễn đàn, mở khóa toàn bộ tính năng VIP mà không tốn đồng nào. Hoặc bạn thấy hàng nghìn tài khoản đăng ký mới trong một đêm, tất cả đều đến từ cùng một dải IP và chạy trên trình giả lập. Đây là hai bài toán mà Play Integrity API được sinh ra để giải quyết.

Play Integrity API là dịch vụ do Google cung cấp, cho phép ứng dụng của bạn hỏi hệ thống Google ba câu hỏi và nhận về câu trả lời có chữ ký số không thể giả mạo: bản app đang chạy có phải bản gốc từ Google Play không, thiết bị đang chạy có đáng tin không, và tài khoản Google đang dùng có thực sự sở hữu giấy phép cài app này không.

1. Play Integrity API thay thế cho SafetyNet Attestation

Trước đây, cách kiểm tra tính toàn vẹn thiết bị phổ biến nhất là SafetyNet Attestation API. Google đã dừng nhận đăng ký mới cho SafetyNet và tắt dần dịch vụ này theo lộ trình nhiều giai đoạn, chuyển toàn bộ sang Play Integrity API. Nếu dự án của bạn còn dùng SafetyNet, đây là khoản nợ kỹ thuật cần trả sớm chứ không phải việc để dành.

Tiêu chíSafetyNet Attestation (cũ)Play Integrity API (hiện tại)
Trạng tháiĐã ngừng nhận dự án mới và tắt dầnĐang được phát triển và mở rộng
Kiểm tra tính toàn vẹn thiết bịCó (basicIntegrity và ctsProfileMatch)Có, chi tiết hơn với nhiều mức phán quyết
Kiểm tra bản app có bị sửa đổi khôngChỉ qua so khớp thủ công dấu vân tay APKCó sẵn, so với bản Google Play đang phân phối
Kiểm tra giấy phép tài khoảnKhông, phải dùng Licensing Verification riêngCó, tích hợp sẵn trong cùng một lần gọi
Chống tấn công phát lại (replay attack)Phải tự xử lý nonceCó cơ chế nonce và requestHash tích hợp

2. Ba nhóm phán quyết Play Integrity API trả về

Kết quả trả về là một token đã ký, sau khi giải mã sẽ cho ra ba nhóm thông tin. Hiểu đúng ý nghĩa từng nhóm là điều kiện bắt buộc để không chặn nhầm người dùng hợp lệ.

2.1. appIntegrity: bản app đang chạy có phải bản gốc không

  • PLAY_RECOGNIZED: app đang chạy đúng là bản do Google Play phân phối, chưa bị sửa đổi. Đây là trạng thái bạn mong muốn.
  • UNRECOGNIZED_VERSION: app có đúng package name nhưng phần nội dung không khớp với bất kỳ bản nào Google Play từng phân phối. Đây chính là dấu hiệu của bản mod, bản crack, hoặc đơn giản là bản debug bạn tự build.
  • UNEVALUATED: Google không đánh giá được, thường vì thiết bị không đáng tin ở mức cơ bản.

2.2. deviceIntegrity: thiết bị đang chạy có đáng tin không

  • MEETS_DEVICE_INTEGRITY: đây là một thiết bị Android thật, có dịch vụ Google, đã vượt qua bộ kiểm thử tương thích. Mức tiêu chuẩn cho phần lớn app.
  • MEETS_BASIC_INTEGRITY: có dấu hiệu là thiết bị Android nhưng không đạt đủ điều kiện của mức trên. Máy đã root, máy chạy ROM tùy biến hoặc một số máy cũ hay rơi vào nhóm này.
  • MEETS_STRONG_INTEGRITY: mức cao nhất, có thêm bảo chứng từ phần cứng và hệ thống khởi động. Chỉ nên yêu cầu mức này cho các nghiệp vụ cực nhạy cảm như ngân hàng.
  • MEETS_VIRTUAL_INTEGRITY: đang chạy trong môi trường ảo hóa được Google công nhận, ví dụ trình giả lập Android Studio. Đây là mức giúp bạn phân biệt máy ảo hợp lệ với máy ảo lậu.
  • Trường rỗng, không có nhãn nào: đây là tín hiệu xấu nhất, thường gặp ở máy đã bị can thiệp sâu hoặc trình giả lập tự chế.

2.3. accountDetails: tài khoản có giấy phép cài app không

  • LICENSED: tài khoản Google này đã cài hoặc mua app từ Google Play một cách hợp lệ.
  • UNLICENSED: app có mặt trên máy nhưng tài khoản không có lịch sử cài đặt hợp lệ từ cửa hàng. Đây là dấu hiệu điển hình của app tải từ trang chia sẻ APK lậu.
  • UNEVALUATED: không đánh giá được, thường do các trường thông tin phía trên đã không đạt.

3. Kiến trúc triển khai đúng chuẩn: vì sao phải xác thực ở máy chủ

Đây là phần bị làm sai nhiều nhất và cũng là phần quyết định toàn bộ giá trị của Play Integrity API.

Luồng đúng gồm bốn bước:

  1. Máy chủ của bạn sinh ra một chuỗi ngẫu nhiên dùng một lần, gọi là nonce, và gửi xuống cho app.
  2. App gọi Play Integrity API kèm theo nonce đó, nhận về một token đã được Google ký.
  3. App gửi token này lên máy chủ của bạn, không tự đọc, không tự quyết định gì cả.
  4. Máy chủ gọi tới Google Play Developer API để giải mã token, đối chiếu nonce, kiểm tra tên gói ứng dụng, rồi mới ra quyết định cho phép hay từ chối.

Sai lầm phổ biến là để chính app giải mã token và tự quyết định. Cách làm này vô nghĩa hoàn toàn, vì kẻ tấn công đã kiểm soát toàn bộ mã nguồn phía client, họ chỉ cần sửa lại đúng một câu lệnh if là mọi lớp kiểm tra biến mất. Nguyên tắc cốt lõi: kết quả kiểm tra phải được diễn giải ở nơi kẻ tấn công không chạm tới được, tức là máy chủ của bạn.

Sai lầm thứ hai là bỏ qua nonce. Không có nonce, kẻ tấn công có thể lấy một token hợp lệ từ thiết bị sạch, lưu lại, rồi phát lại token đó mãi mãi từ môi trường đã bị can thiệp.

4. Standard request và Classic request: chọn loại nào

Tiêu chíStandard requestClassic request
Độ trễVài trăm mili giây, có bước làm nóng trướcCao hơn đáng kể, thường vài giây
Chi phí tài nguyên trên thiết bịThấp, dùng lại kết quả đã lưu đệmCao, tính toán lại từ đầu mỗi lần
Hạn mức gọiRộng rãi, phù hợp gọi thường xuyênHạn mức chặt, cần xin nâng nếu vượt
Phù hợp vớiKiểm tra định kỳ trong luồng sử dụng bình thườngCác hành động giá trị cao, hiếm khi xảy ra
Chống replayDùng requestHashDùng nonce do bạn tự sinh

Nguyên tắc chọn trong thực tế: dùng Standard request cho mọi kiểm tra thường xuyên như mở app, vào màn hình chính, gọi API dữ liệu. Dành Classic request cho những khoảnh khắc đắt giá và hiếm gặp như hoàn tất giao dịch lớn, rút tiền, hoặc nhận thưởng có giá trị. Gọi Classic request ở mọi màn hình là cách nhanh nhất để cháy hạn mức và làm app chậm đi thấy rõ.

5. Đoạn mã tối thiểu phía Android

val manager = IntegrityManagerFactory.createStandard(context)

// Bước làm nóng, gọi sớm khi app khởi động
val tokenProvider = manager.prepareIntegrityToken(
    PrepareIntegrityTokenRequest.builder()
        .setCloudProjectNumber(CLOUD_PROJECT_NUMBER)
        .build()
)

// Khi cần kiểm tra một hành động cụ thể
val requestHash = sha256(userId + actionName + serverNonce)
tokenProvider.request(
    StandardIntegrityTokenRequest.builder()
        .setRequestHash(requestHash)
        .build()
).addOnSuccessListener { response ->
    // KHÔNG tự giải mã ở đây, gửi thẳng lên máy chủ
    sendToBackend(response.token())
}

Điểm cần nhấn mạnh trong đoạn mã trên là dòng comment cuối cùng. App chỉ làm nhiệm vụ chuyển tiếp token, mọi logic quyết định nằm ở phía máy chủ.

6. Bảng chiến lược phản ứng theo từng kết quả

Nhận được phán quyết rồi thì làm gì tiếp? Đây là nơi phân biệt một triển khai chín chắn với một triển khai gây hại cho chính sản phẩm của bạn.

Kết quả nhận đượcPhản ứng nên làmPhản ứng KHÔNG nên làm
Mọi thứ đều đạtCho dùng bình thườngKhông có gì
UNRECOGNIZED_VERSIONHiện hộp thoại lịch sự mời người dùng cài lại app từ Google Play, kèm nút mở thẳng trang cửa hàngThoát app đột ngột không giải thích
UNLICENSEDGiới hạn tính năng trả phí, mời mua chính thứcXóa dữ liệu người dùng
Chỉ đạt MEETS_BASIC_INTEGRITYCho dùng nhưng chặn các nghiệp vụ nhạy cảm, ghi log để phân tíchChặn hoàn toàn, vì rất nhiều người dùng thật đang chạy máy root hoặc ROM tùy biến
Trường phán quyết rỗngĐưa vào diện rủi ro cao, tăng cường xác thực bổ sungCoi như lỗi hệ thống rồi cho qua
Gọi API thất bại vì mất mạngCho phép dùng offline có giới hạn, thử lại sauKhóa app, vì đây là lỗi hạ tầng chứ không phải gian lận

7. Kết hợp Play Integrity với các lớp bảo vệ khác

Play Integrity API là một lớp, không phải toàn bộ hệ thống phòng thủ. Một sản phẩm có doanh thu thật nên xếp chồng nhiều lớp:

  • Xác minh giao dịch phía máy chủ: mọi giao dịch In-App Purchase phải được xác thực lại bằng Google Play Developer API trước khi cấp quyền lợi, không bao giờ tin vào kết quả client trả về. Xem bài tích hợp Google Play Billing SDK v6.
  • Theo dõi hoàn tiền gian lận: kết hợp với Voided Purchases API để thu hồi quyền lợi của những giao dịch đã bị hoàn tiền, chi tiết trong bài chống gian lận hoàn tiền bằng Google Play Developer API.
  • Làm rối mã nguồn: bật R8 với cấu hình tối ưu để tăng chi phí dịch ngược, xem bài tối ưu dung lượng AAB APK với R8.
  • Giới hạn tần suất phía máy chủ: chặn theo tài khoản và theo thiết bị, vì kẻ tấn công có tổ chức luôn tìm được cách vượt qua từng lớp riêng lẻ.

8. Khi nào KHÔNG nên dùng Play Integrity API

Đây là phần mà tài liệu tiếp thị của mọi nhà cung cấp đều bỏ qua, nhưng nó quyết định việc bạn có làm hỏng sản phẩm của mình hay không.

  • App miễn phí hoàn toàn, không có dữ liệu nhạy cảm: chi phí triển khai và rủi ro chặn nhầm lớn hơn lợi ích thu được. Một app đọc tin tức không cần biết máy người dùng có root hay không.
  • App phân phối ngoài Google Play: phán quyết về giấy phép và bản app sẽ luôn báo không đạt, vì hệ thống đối chiếu với dữ liệu của cửa hàng. Nếu bạn phát hành song song trên nhiều kho ứng dụng, hãy tách biến thể build và chỉ bật kiểm tra cho biến thể Google Play.
  • App phục vụ thị trường có tỷ lệ máy root và ROM tùy biến cao: chặn cứng ở mức thiết bị có thể khiến bạn mất một phần đáng kể người dùng thật. Hãy ghi log trước trong vài tuần để đo tỷ lệ thực tế rồi mới quyết định ngưỡng chặn.
  • App bắt buộc chạy offline: Play Integrity cần kết nối mạng để lấy phán quyết. Ứng dụng dùng trong môi trường không có internet ổn định sẽ liên tục rơi vào trạng thái không đánh giá được.
  • Bạn chưa có backend: nếu toàn bộ logic nằm ở client, việc tích hợp Play Integrity chỉ tạo cảm giác an toàn giả. Hãy dựng máy chủ xác thực trước rồi mới tính tới bước này.

9. Quy trình 5 bước triển khai không làm hỏng trải nghiệm

  1. Giai đoạn quan sát: tích hợp API nhưng chỉ ghi log, không chặn bất kỳ ai. Chạy tối thiểu hai tuần để có mẫu số liệu đủ lớn.
  2. Phân tích phân bố phán quyết: xem bao nhiêu phần trăm người dùng thật đang rơi vào từng nhóm. Nếu tỷ lệ không đạt vượt quá vài phần trăm, ngưỡng bạn định đặt là quá chặt.
  3. Bật chặn cho nghiệp vụ hẹp nhất trước: chỉ chặn ở đúng một hành động giá trị cao, không chặn ở màn hình khởi động.
  4. Phát hành dần bằng Staged Rollout: bắt đầu từ 5 phần trăm người dùng và theo dõi chỉ số gỡ cài đặt cùng điểm đánh giá, tham khảo bài Staged Rollout trên Google Play.
  5. Chuẩn bị sẵn công tắc tắt từ xa: đặt cờ bật tắt trong cấu hình từ xa để có thể vô hiệu hóa việc chặn ngay lập tức nếu số liệu xấu đi, không cần chờ duyệt bản cập nhật.

Kết luận

Play Integrity API không phải là lá chắn tuyệt đối và cũng không nên được kỳ vọng như vậy. Giá trị thật của nó là nâng chi phí tấn công lên đủ cao để phần lớn kẻ crack nghiệp dư bỏ cuộc, đồng thời cho bạn dữ liệu để nhận diện các luồng gian lận có tổ chức. Ranh giới giữa một triển khai tốt và một triển khai gây hại nằm ở chỗ bạn có xác thực token ở máy chủ hay không, và bạn có kiên nhẫn quan sát số liệu trước khi bật chặn hay không.

Nếu bạn đang xây dựng app có doanh thu và cần tư vấn kiến trúc bảo vệ từ khâu thanh toán tới khâu phân phối, Uwmee Software nhận đồng hành từ giai đoạn thiết kế hệ thống. Bài liên quan nên đọc: Google Play chặn APK và lộ trình bắt buộc AAB cùng mô hình Hybrid Monetization kết hợp AdMob và In-App Purchase.

Câu hỏi thường gặp

Bạn cần giải pháp phần mềm chuyên nghiệp?

Uwmee Software cung cấp dịch vụ 12 tester Google Play & thiết kế website cao cấp giúp nâng tầm thương hiệu của bạn.