Android Developers Blog
The latest Android and Google Play news for app and game developers.
🔍
Platform Android Studio Google Play Jetpack Kotlin Docs News

13 November 2017

10 things you might be doing wrong when using the SafetyNet Attestation API


Link copied to clipboard

Posted by Oscar Rodriguez, Partner Developer Advocate

[Note: This blog was amended in March 2018 to include our latest recommendations regarding app integrity verification, in May 2019 to amend the quota increase request form link, and in July 2022 to announce the deprecation of this API.]

[Note: The SafetyNet Attestation API is now deprecated. This blog post remains for reference, but new and existing developers should use the Play Integrity API instead.]

The SafetyNet Attestation API helps you assess the security and compatibility of the Android environments in which your apps run. Since it was introduced in March 2015, many developers have successfully integrated it into their Android apps to make more informed decisions based on the integrity and compatibility of the devices running their apps.

Throughout the years, the SafetyNet Attestation API has evolved, and its adoption has steadily increased. However, as with any security/anti-abuse related API, there are many common pitfalls that may lead developers into developing unstable systems, or worse, into a false sense of security.

In this post, we provide a list of the most common mistakes we have seen developers make when integrating the SafetyNet Attestation API.

1. Not getting an API key

Just like many other Google APIs, the SafetyNet Attestation API requires an API key in order to run. Furthermore, the SafetyNet Attestation API has a per-key usage quota. Although you can get this quota increased, you need to provide your API key to do so.

Getting an API key is easy and free of charge. There is no reason not to get an API key, so if you haven't already, get an API key now.

2. Not using the latest version of the API

The SafetyNet Attestation API has evolved throughout its history, and with it, there have been some interface changes. Most recently, with the release of Google Play services 11.0.0, we revamped the entire SafetyNet API to offer an interface that is easier and more streamlined to use: the new API uses SafetyNetClient instead of SafetyNetApi, which is now deprecated, so make sure you update your implementation to use the latest version of the API.

Most devices should have the latest version of Google Play services installed, but if a device doesn't have Google Play services installed, or doesn't have it up to date, using the SafetyNet Attestation API may lead to the app becoming unresponsive or crashing. You can prevent this by checking the installed version of Google Play services before using the API.

3. Using nonces incorrectly

The SafetyNet Attestation API lets you set a nonce to uniquely and globally identify each call to the API. Use this feature to prevent a malicious user from reusing a successful attestation result in place of an unsuccessful result (also known as a Replay Attack).

One good way to create a nonce is to create a large (16 bytes or longer) random number on your server using a cryptographically-secure random function. The SafetyNet attestation response includes the nonce you set, so make sure you verify that the returned nonce matches the one you included in the request you made.

4. Not checking the results on your server

SafetyNet can provide useful signals about the state of the device in which your app is running. However, if the logic that acts on these signals is only implemented and enforced directly on the device, an attacker could be able to modify your app and bypass any checks you perform.

To prevent this situation, you should run any logic that verifies the attestation result and enforces any actions based on them on a server that you control and trust.

5. Using the test attestation verification service for production

In order to simplify development and testing of the SafetyNet Attestation API, Google offers an online verification service that checks the digital signature of a SafetyNet Attestation result using a simple HTTPS request.

As useful as this service may seem, it is designed for test purposes only, and it has very strict usage quotas that will not be increased upon request. Instead, you should implement the digital signature verification logic on your server in a way that it doesn't depend on Google's servers. Most JWT libraries offer signature verification functionality, and we have code samples that show how to perform this verification in Java and C#. We plan to provide samples for more languages in the future.

6. Not checking the nonce, timestamp, APK name, and hashes

The SafetyNet Attestation API is most widely known for its integrity and compatibility checks, whose results are returned in ctsProfileMatch and basicIntegrity. Although these two values are indeed very useful, you should check the other values in the response, as they contain important information as well.

Use nonce to match a response to its request, as explained above, and use timestampMs to check how much time has passed since you made the request and you got the response. A delayed response that arrives several hours or days after the request may suggest suspicious activity.

Use apkPackageName to check the name of the APK that made the attestation request, and match apkDigestSha256 and apkCertificateDigestSha256 to those from your app's signed APK in Google Play, to get a signal about the integrity of the installed app.

You can also use apkDigestSha256 to check the hash value of the APK installed on the user device. Be aware, however, that distribution channels, such as Google Play may include additional metadata into the APK, so apkDigestSha256 might differ from the hash value of the APK that you uploaded to your distribution channel. In most cases, using apkPackageName and apkCertificateDigestSha256 should be sufficient signals for verifying the integrity of the APK.

Remember that the trustworthiness of the response as a whole is tied to the results of ctsProfileMatch and basicIntegrity. It is not unthinkable for a compromised device that fails basicIntegrity to have forged the rest of the values in the response.

7. Not understanding the differences between ctsProfileMatch and basicIntegrity

The SafetyNet Attestation API initially provided a single value called basicIntegrity to help developers determine the integrity of a device. As the API evolved, we introduced a new, stricter check whose results appear in a value called ctsProfileMatch, which allows developers to more finely evaluate the devices on which their app is running.

In broad terms, basicIntegrity gives you a signal about the general integrity of the device and its API. Rooted devices fail basicIntegrity, as do emulators, virtual devices, and devices with signs of tampering, such as API hooks.

On the other hand, ctsProfileMatch gives you a much stricter signal about the compatibility of the device. Only unmodified devices that have been certified by Google can pass ctsProfileMatch. Devices that will fail ctsProfileMatch include the following:

  • Devices that fail basicIntegrity
  • Devices with an unlocked bootloader
  • Devices with a custom system image (custom ROM)
  • Devices for which the manufactured didn't apply for, or pass, Google certification
  • Devices with a system image built directly from the Android Open Source Program source files
  • Devices with a system image distributed as part of a beta or developer preview program (including the Android Beta Program)

8. Not having a strategy for timing attestation checks

The SafetyNet Attestation API gives you a snapshot of the state of a device at the moment when the attestation request was made. A successful attestation doesn't necessarily mean that the device would have passed attestation in the past, or that it will in the future.

Because an attestation is just a spot check, you should plan a sensible strategy for choosing when to make attestation requests. You may choose to require successful attestations before users make in-app purchases, after a certain number of days have passed since the last successful attestation, each time your app is launched, after every reboot, or any other strategy that makes sense for your app.

Keep in mind that an attestation request is computationally expensive, consumes battery and bandwidth, and uses your quota. We recommend you plan a strategy to use the least amount of attestations required to satisfy your use case.

9. Using the SafetyNet Attestation API results as the only signal to attack abuse

It may be tempting to think that the SafetyNet Attestation API provides all the necessary signals for protecting an app against abusers, and use it as the only signal for building an anti-abuse system.

The SafetyNet Attestation API can only give signals about the state of a device, not the intent of a user, which is what an anti-abuse system should be designed to detect. Therefore, you might want to consider including other signals, such as access logs and behavioral patterns, to more accurately detect abusive users, and consider not blocking users solely on a failed attestation. Furthermore, there are many other conditions that cause an attestation to fail, such as network connection problems, quota issues, and other transient problems.

In other words, not all users who fail attestation are necessarily abusers, and not all abusers will necessarily fail attestation. By blocking users solely on their attestation results, you might be missing abusive users that don't fail attestations. Furthermore, you might also be blocking legitimate, loyal customers who fail attestations for reasons other than abuse.

10. Not monitoring and managing your usage quota

As mentioned before, the SafetyNet Attestation API is rate limited, and there is a default quota of 10,000 requests per day for each API key. Although this quota might be enough for most development, testing, and initial app launches, your app might reach the default limit as it increases in popularity.

To prevent inadvertently reaching your quota and getting attestation errors, you should build a system that monitors your usage of the API and warns you well before you reach your quota so you can get it increased. You should also be prepared to handle attestation failures because of an exceeded quota and avoid blocking all your users in this situation.

If you are close to reaching your quota, or expect a short-term spike that may lead you to exceed your quota, you can submit this form to request short or long-term increases to the quota for your API key. This process, as well as the additional quota, is free of charge.