Magisk may no longer be able to hide bootloader unlocking from apps
XDA 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.
In order to root your phone, you usually need to unlock the bootloader, which allows you to flash modified boot images. This is needed because Magisk modifies the boot image to spoof bootloader status and/or the Verified Boot status checks. Google’s SafetyNet Attestation API, which is part of Google Play Services, is used to tell an app if it’s running on a tampered device; if the SafetyNet API detects that the bootloader has been unlocked, then it will return a failure status for the “Basic Integrity” check. Devices that fail this check can then be locked out from apps that use the SafetyNet API to determine the device integrity; such apps typically include banking apps, payment apps (like Google Pay), and many online games (like Pokémon Go). However, because the SafetyNet API has thus far only used software checks to determine if the device has been tampered with, Magisk can simply spoof the bootloader and/or Verified Boot status since it is installed at a lower level and with higher privileges than Google Play Services and other userspace applications. As topjohnwu explains, MagiskHide “[creates] an isolated ‘safe environment’ for the detection process, and it goes through Google’s API to create a legit SafetyNet result that does not reflect the real status of the device.”
Recently, though, users have noticed that their bootloader-unlocked devices are failing SafetyNet’s Basic Integrity check even though they used Magisk to patch the boot image. According to topjohnwu, this is because Google may have implemented hardware-level key attestation to verify that the boot image has not been tampered with. Specifically, this means Google Play Services “[sends] an unmodified keystore certificate to SafetyNet servers, verify its legitimacy, and check certificate extension data to know whether your device [has] verified boot enabled (bootloader status).” This means that it may no longer be possible to hide the fact that the bootloader has been unlocked, which will result in applications like Google Pay and Pokémon Go failing to operate normally.
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.
Yes, we will revoke them. If the keys are leaked, we’ll revoke them. If the firmware has an unrecoverable flaw, we’ll revoke them. If the firmware has a flaw that can be fixed via OTA, we’ll analyze the situation to decide if that is adequate.
— Shawn Willden (@shawnwillden) March 11, 2020
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 doable 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 check used hardware-based attestation as this would allow app developers to decide if they want to block all users who have unlocked the bootloader.
Thanks to Daniel Micay (@DanielMicay) for his input regarding this matter!