Attestation on Android and iOS Is Not as Secure as You Think

App attestation is a security process that verifies if an app is genuine, unmodified, and running on a secure device. In simple terms, app attestation is a service that runs security checks and returns a verdict. Both Google and Apple offer app attestation services to help developers protect their apps. In this post, we'll explore what makes for an ideal attestation service and review Android's KeyAttest and Play Integrity, as well as iOS's App Attest.
What makes for a perfect app attestation service?
An application is considered genuine and unmodified when its code hasn't been altered since it was built and signed by the developer. When the system launches the app, it reads the code from the application package, loads it into memory, and executes it. An attacker can modify the code either:
- In the application package before launch, or
- In memory during runtime.
Attackers usually tamper with the business logic of the app to:
- Unlock paid features.
- Replace the camera feed for face authentication.
- Add spyware code.
- Cheat in games.
Tampered application packages are often referred to as “mods”. Attackers distribute them as APK or IPA files – either for a fee to game cheaters, or through a phishing campaign to victims.
Tampering with code in memory is typically done by the bad actors as it requires running the app on a device with elevated privileges (such as a rooted or jailbroken mobile device, or an emulator on a PC).
Devices with elevated privileges enable the attackers to modify not only the application’s code at runtime but also all the code in system libraries as well.
With these risks in mind, mobile application developers need protections that can ensure:
- Application package integrity.
- Code at runtime integrity.
- Device integrity.
But these are really just “basic” requirements. A more advanced attestation service should also:
- Have a secure and efficient architecture.
- Collect evidence about the app, device, and code in a broad and stealthy way.
- Continuously improve real-time detection by analyzing data from thousands of devices.
- Provide detailed insight into each verdict, so you can reconsider policies on the fly.
- Work across all your apps regardless of the platform.
Before we dive into comparing the different mobile app attestation services, let’s shine a light on the techniques behind them to better understand what really sets them apart.
A secure and efficient architecture
Attestation services are typically designed around one of two different workflows – but only one of them enables continuously up-to-date verdicts for every single request. Nevertheless, let's review both to better understand and compare the designs.
Backend-integrated attestation architecture
The diagram below shows a simplified app attestation workflow, where the app performs security tests and sends evidence to the backend API. Once the server collects enough evidence, it creates a cryptographically signed verdict and sends it to the app. From now on, the app adds this verdict to every HTTPS request as a means of authentication.
This design is simple, but it doesn’t use the full potential of server-side threat analysis because the backend device attestation server collects data only from one application across many devices or requires periodic out-of-band signature updates. This architecture is more commonly seen in DIY solutions and scenarios where application developers can only rely on the limited context of their own app installs.
Dedicated app attestation server architecture
Preferably, we want to collect data from many applications across many devices and have the ability to trigger real-time verdict updates as of the next request. The more apps and devices the attestation server collects evidence from, the faster and more robust the threat detection will be. For example, if a new attack technique against one app is found, the attestation server can immediately use this knowledge to protect all the other apps.
Collect evidence in a broad and stealthy way
Most mobile app protections work by running a series of simple true/false checks. For example, to detect if the app is running on an emulator, a protection solution might look for the presence of a specific file in the filesystem. If that check passes, the solution will move on to the next one (and so on) until something suspicious is found.
App attestation services may take a different approach. Instead of looking for one specific file, the app attestation service can collect broader system data – like a list of all files along with their checksums – and send it to a server for validation. This lets the server spot unexpected changes or anomalies in a more reliable way.
This method also makes attestation services more flexible and powerful. They're able to catch a wider range of threats by analyzing patterns and deviations rather than relying on predefined checks.
Improve real-time detection by analyzing data from thousands of devices
In reality, no software is perfectly secure and you can't protect your app from all threats without continuously working on your defenses. The key is to recognize as quickly as possible when the software isn't behaving as intended and then swiftly respond. With a large amount of gathered evidence from thousands of devices, app attestation can easily identify outliers and emerging threats. Once you understand how the attack works, your attestation service would ideally detect it without requiring an app redeployment to the Play Store or App Store. An attestation service with a broad view of many apps across many devices has all the necessary data to quickly find and respond to new threats without the need for an application update.
Provide insight into each verdict and update policies on the fly
By collecting a broad and complete picture of the application’s behavior, we can easily identify outliers and define rules on the app attestation server to block devices that exhibit such patterns.
Work across all apps, regardless of platform
App attestation shouldn’t be limited to a single platform. If an app is experiencing malicious bot activity and you've already addressed it on Android, there’s no reason to start over for iOS. A good solution provides a more integrated view – by leveraging user IDs, you can track behavior across platforms and enforce consistent security policies.
Android’s Play Integrity review
To speed up the reviewing process, let’s take an open-source implementation of Android’s Play Integrity Checker attestation. Android app attestation is run and then results are displayed onscreen. Below, you can find a sample output from a rooted Pixel 3 device:
We can see that Play Integrity checked both Device Integrity and Application Package Integrity.
- The Device Integrity score provides information about the device state (e.g., is the device including Google Play Service; is the bootloader unlocked; did the device perform a security update in the last year).
- The Application Package Integrity section reveals the package name and certificate hash, so that a developer can verify that the app is correctly signed with their own key.
Listed below are a few common attacks against attestation services using Play Integrity as an example. Later, we’ll dive into more advanced attacks specifically targeting Play Integrity.
In the current Play Integrity setup for this demonstration application, the app attestation service runs security checks and issues the verdict locally.
Attack example #1: Intercept and spoof the verdict locally.
An attacker can intercept and spoof the verdict. Depending on the type of attack, an attacker can tamper with the logic statically inside the application package, or modify the logic at the runtime by using a debugger or Frida.
This is why Play Integrity and similar solutions strongly recommend having a remote server that verifies the verdict on a secure remote server. However, an attacker can still target the security checks.
Attack example #2: Intercept and spoof attestation’s security checks.
An attacker can intercept and spoof security checks. For example, Play Integrity verifies factors such as whether the device's bootloader is unlocked, certain files are present, or SELinux is enforced to assess the device's security. In recent years, attackers have published many tools to spoof Play Integrity checks.
To mitigate this kind of spoofing attack, a robust app attestation service should collect a broader set of evidence about the app and system rather than relying on a fixed list of predefined properties. This forces an attacker to forge a complete and internally consistent view of a healthy environment – something that’s much harder to achieve. Since Play Integrity is a closed source, it’s difficult to assess exactly how it gathers and verifies this data.
Attack example #3: Reuse the verdict token from another device.
Attackers can also obtain a valid verdict token from an app on a healthy device and then reuse it on a modified app or with an insecure device.
This is why it’s recommended to bind the verification token to the mobile device and use that binding when communicating with the server component. You can read more about Device Binding in our previous blog post.
One technique that plays an important role in Play Integrity is KeyAttestation. It leverages the TEE to get cryptographic proof of the device’s status. However, this is also often targeted by attackers:
Attack example #4: Spoof the app attestation verdict with a leaked OEM key.
All official Android phone manufacturers (OEMs) hold multiple private keys to sign attestation verdicts on their devices. These keys regularly get leaked as a result of security breaches or other unintentional exposures. The problem has become so widespread that tools like this were created to forge attestation verdicts for any Android device. Google tries to minimize this issue by maintaining a Revocation List of compromised keys, but there’s typically some delay before leaked keys can be added.
Additionally, some rooting techniques don’t rely on unlocking the bootloader, so by design they are not detected by KeyAttestation:
Attack example #5: Use an exploit to tamper with the app.
To verify a device's security, KeyAttestation checks whether the bootloader is unlocked. An unlocked bootloader indicates that a third-party system image is installed on the device. However, an attacker can use one of many publicly accessible exploits to escalate privileges without affecting the bootloader. For example, the Dirty COW exploit has been widely used to gain root access on Android devices, allowing attackers to hook code, scan memory, and tamper with data files.
Both attacks can fully compromise the Play Integrity attestation service, allowing the attacker to alter app logic, tamper with memory, and modify the app’s storage. Since Play Integrity Android app attestation runs outside the app’s process, it lacks full visibility into the app’s internal state.
Attack example #6: Use a third-party app with an accessibility service to spy on or control the targeted app.
Attackers trick victims into installing a malicious app either via the PlayStore or by sideloading. Once the user grants the malicious app “accessibility service” permission, it can log all the user's activity and then send it to the attacker’s backend.
Summary
The table below shows how many of the “advanced app attestation requirements” are currently fulfilled by Play Integrity:
Feature | Play Integrity |
---|---|
1. Test app package integrity | YES ✅ |
2. Test code integrity | NO ❌ |
3. Test device security | YES ✅ |
4. Use a secure and efficient architecture | YES ✅ |
5. Collect evidence in a broad and stealthy way | PARTIALLY |
6. Analyze thousands of devices in real-time | UNKNOWN |
7. Provide detailed insight into each verdict | NO ❌ |
8. Work across all apps, regardless of platform | NO ❌ |
iOS’s App Attest review
App Attest, an iOS app attestation service, only verifies an app's authenticity, which means it only protects against application package tampering. The logic behind the checks is simple: App Attest collects the TeamID and BundleID of the currently running app and sends them to the server. Apple guarantees that no other developer can create an app with the same IDs.
Once the App Attest server receives these IDs, it issues a signed token containing both IDs. The server sends the token back to the device, and the application running on the device will then attach the token to all HTTPS requests to the backend server. The backend server uses this token to authenticate the device. It first verifies the integrity of the token and then makes sure BundleID and TeamID are both as expected.
Below, you can see some sample information returned by App Attest:
Example attack #1: An attacker uses a jailbroken device.
A jailbroken device enables an attacker to tamper with app code in the runtime without changing TeamID and BundleID. This means that the App Attest will collect the original IDs and the verdict will show the app as verified.
Example attack #2: An attacker uses TrollStore to repackage the app.
All iOS versions from 14.0 to 17.0 are affected by the CoreTrust bug, which enables a device user to sideload an app with an arbitrary BundleID and TeamID. This means that an attacker can tamper with the app and distribute it online.
Below is a breakdown of how many 'advanced app attestation requirements' are fulfilled by Apple’s App Attest
Feature | App Attest |
---|---|
1. Test app package integrity | YES ✅ |
2. Test code integrity | NO ❌ |
3. Test device security | NO ❌ |
4. Use a secure and efficient architecture | YES ✅ |
5. Collect evidence in a broad and stealthy way | NO ❌ |
6. Analyze thousands of devices in real-time | NO ❌ |
7. Provide detailed insight into each verdict | NO ❌ |
8. Work across all apps, regardless of platform | NO ❌ |
iOS’s DeviceCheck review
DeviceCheck is not an app attestation service, but it is sometimes mistaken as one. It simply provides a secure way to set and query two bits per device, which can help enforce business logic – but it doesn’t actually offer any device integrity checks.
Summary
Play Integrity and App Attest address the basic security needs of an application. They can reliably detect tampering with the app package on clean devices, but they fall short against more sophisticated attacks observed in the wild, as we've outlined above.
Since threat actors are constantly developing new methods, an ideal app attestation service must be able to detect and block attacks in real-time. This becomes far more effective when the app attestation service has visibility into a broad range of running devices – especially those that show abnormal behavior – and can apply that insight across other apps.
Feature | Play Integrity | App Attest |
---|---|---|
1. Test app package integrity | YES ✅ | YES ✅ |
2. Test code integrity | NO ❌ | NO ❌ |
3. Test device security | YES ✅ | NO ❌ |
4. Use a secure and efficient architecture | YES ✅ | YES ✅ |
5. Collect evidence in a broad and stealthy way | PARTIALLY | NO ❌ |
6. Analyze thousands of devices in real-time | NO ❌ | NO ❌ |
7. Provide detailed insight into each verdict | NO ❌ | NO ❌ |
8. Work across all apps, regardless of platform | NO ❌ | NO ❌ |