DA Recognized Developer topjohnwu‘s “Magisk” project has essentially become synonymous with “root” in the Android community. One of the main reasons it’s so popular is because it can hide the fact that the user has modified their device. However, Google may be cracking down on the ability of Magisk to hide the bootloader unlock status from applications.
So here we go, after years of fun messing around using Magisk, it seems that Google FINALLY decided to "fix" SafetyNet to something useful, and that is to use key attestation to verify device status (after 3 years since introduced to Android's platform!)
— John Wu (@topjohnwu) March 11, 2020
As topjohnwu noted, this change to the way that SafetyNet checks the bootloader unlock status comes through a server-side update to the SafetyNet API contained in Google Play Services. However, not every user is failing these updated SafetyNet checks, so the new hardware-level key attestation may not be widely enforced yet.
We’ve seen topjohnwu overcome technical hurdles time and time again. Google frequently rolls out new checks in SafetyNet that topjohnwu then discovers and bypasses in Magisk. Each new version of Android brings changes to the partition structure or boot image, requiring topjohnwu to study the changes and then implement a new patching method. However, even topjohnwu may struggle to find a bypass this time around.
That’s because the workaround this time would involve hacking the Trusted Execution Environment (TEE) firmware of devices in order to retrieve the private key. However, this is incredibly difficult to do as it requires finding a vulnerability in firmware that is designed to be incredibly secure. In fact, many companies offer payments in the hundreds of thousands of dollars if such a vulnerability were to be found. Google, for instance, pays $250,000 for remote code execution vulnerabilities in the Pixel’s Trusted Execution Environment, and up to $1,000,000 for vulnerabilities in the Titan M security chip. Even if a private key were somehow to be leaked, it’s unlikely that it would be of much use since Google can remotely revoke the key so it can’t be used to verify the integrity of devices.
Reason Behind How It Was Work
Once hardware-level key attestation is widely enforced for SafetyNet, most devices with unlocked bootloaders running Android 8.0 Oreo or higher will fail to pass SafetyNet’s Basic Integrity check. This is because all devices that launched with Android 8.0 Oreo or higher are required to have a hardware Keystore implemented in a TEE. Certain devices nowadays even have dedicated hardware security modules (HSMs) that make exploitation even more difficult by moving the TEE away from the main processor; the Titan M in the Pixel 4 and Samsung’s new security chip in the Galaxy S20 are examples of this.
Topjohnwu also explains that other potential workarounds are either impossible or highly challenging. Using the Xposed Framework to modify the SafetyNet Attestation API in Google Play Services likely won’t work since “proper SafetyNet checks will verify results on a remote server, not on [the] device which can be manipulated by code injection frameworks.” Furthermore, Google Play Services is highly obfuscated, making the creation of such an Xposed Module incredibly challenging in the first place. Spoofing a SafetyNet test result won’t be done either since the SafetyNet responses “come from Google servers and are signed with Google’s private key.”
Google has had the ability to harden SafetyNet checks using hardware-backed key attestation for several years now. The fact that they refrained to do so for 3 years has allowed users to enjoy root and Magisk Modules without sacrificing the ability to use banking apps. However, it seems that Magisk’s ability to effectively hide the bootloader unlock status is soon coming to an end. It’s a change that we’ve expected for years, but we’re sad to see it finally go into effect. We hope that Google updates the SafetyNet Attestation API to return whether the status checks used hardware-based attestation as this would allow app developers to decide if they want to block all users who have unlocked the bootloader.