Qualcomm's TrustZone kernel supports loading Trustlets into Qualcomm's Secure Execution Environment (QSEE). These trustlets are signed, and their signature is verified when they are loaded by the kernel. See https://www.qualcomm.com/documents/secure-boot-and-image-authentication-technical-overview for details. However, on the Nexus 6P and the Nexus 6 (and possibly other devices) there seems to be a lack of revocation for known "bad" trustlets - meaning any trustlet that is signed for a device can be loaded by any version of QSEE, regardless of whether it is known to contain a vulnerability. Once a vulnerability is found in any version of a trustlet for a specific device, an attacker can simply re-load the old vulnerable trustlet even on updated versions of the device, and gain execution within QSEE by exploiting the old vulnerability. This means that simply fixing vulnerabilities in trustlets is not sufficient (and in fact, does not affect the attacker at all). I have previously written a QSEE exploit which I disclosed here: https://github.com/laginimaineb/cve-2015-6639 I just checked, and the same exploit works on the most recent version of the Nexus 6 - NMR1. Instead of using the provided trustlet, just bundle the old vulnerable trustlet with the exploit, and load it instead. See attached exploit archive (QSEE_Exp.tar.gz) - just extract the contents of "EXTRACT_TO_DATA_LOCAL_TMP" to "/data/local/tmp" and then compile and run the exploit. Similarly, I've copied an old version of widevine (from MDA89D) onto a fully updated Nexus 6P, and I've been able to successfully load and interact with it (although, in this case, I don't have a relevant QSEE vulnerability for widevine on the Nexus 6P). See attached PoC (QSEETestLoopWV.tar.gz). This bug is subject to a 90 day disclosure deadline. If 90 days elapse without a broadly available patch, then the bug report will automatically become visible to the public.
Apr 20 2017,
I just ran the same experiment on a fully updated Pixel (NHG47K), and it seems to successfully load and execute an old version of Widevine as well. Here are the MD5 hashes of the current version of Widevine on the Pixel: c95a77f52ebf4c37903a618f294cb67d /vendor/firmware/widevine.b00 bade4495b8da2f36d9863fafc90c0bda /vendor/firmware/widevine.b01 3bf72ffb22ae30ef122ce05e81f7b137 /vendor/firmware/widevine.b02 552a7f8f0d0e569c34ea2987040c5b6c /vendor/firmware/widevine.b03 8aeff13b741c51823ceee6107a57aa2c /vendor/firmware/widevine.b04 c9910719ba67a989544ee45d4b0342f0 /vendor/firmware/widevine.b05 0564c190526d39c823ac3aa10f9717eb /vendor/firmware/widevine.b06 1e4d53c3e7c2bd346e52fba798f7eaf6 /vendor/firmware/widevine.mdt And here are the hashes from an older version: c95a77f52ebf4c37903a618f294cb67d /data/local/tmp/widevine.b00 2eb54f9fc5e717d99d6a1642627352e6 /data/local/tmp/widevine.b01 3bf72ffb22ae30ef122ce05e81f7b137 /data/local/tmp/widevine.b02 552a7f8f0d0e569c34ea2987040c5b6c /data/local/tmp/widevine.b03 8aeff13b741c51823ceee6107a57aa2c /data/local/tmp/widevine.b04 c9910719ba67a989544ee45d4b0342f0 /data/local/tmp/widevine.b05 0564c190526d39c823ac3aa10f9717eb /data/local/tmp/widevine.b06 9e7ac75673efa16fb347498863d5b772 /data/local/tmp/widevine.mdt Note that the b01 block has changed (and the mdt has also changed, since it contains the hashes and signatures for all block files). I'm not sure whether this means that the Pixel lacks revocation as well, but it certainly seems like loading old trustlets is possible on the Pixel as well.
Apr 21 2017,
Attaching the exact binaries used on the Pixel.
Apr 25 2017,
According to the document above (https://www.qualcomm.com/documents/secure-boot-and-image-authentication-technical-overview), the revocation of QSEE trustlets can be performed by incrementing the upper 32-bits of the SW_ID OU in the trustlet's certificate. I've written a short script to extract the version field from the SW_ID for all QSEE trustlets and ran it on my firmware repository. It seems that apart from a single firmware image, every single image uses version "0" for all trustlets (including the trustlets mentioned above). I'm attaching the script (extract_sw_id_field.py) and the results I got from running it on my firmware repository (sw_ids.txt).
Jun 5 2017,
Android have provided the following statement: "The Android security team would like to thank Gal Beniamini and Project Zero for the coordinated disclosure of this security vulnerability. To take effect, this vulnerability requires that the target device is already compromised by another vulnerability. By default, locked Google Pixel, Pixel XL, Nexus 6P, Nexus 6, Nexus 5X, Nexus 9, Pixel C, and Nexus Player devices do not expose the ability to leverage this issue without an exploit chain through a privileged process. The current anti-rollback mechanism requires a hardware fuse to be present and set on devices. This is a useful security feature that device manufacturers may choose to implement on certain devices. The Android platform doesn't require anti-rollback protection, and so this feature is only implemented on some devices. For this reason, the Android Security team evaluated the original vulnerability report as a request for a security feature. However, all anti-rollback mechanisms require incrementation of the Trustlet's version number when a security update is applied. Performing this step is a trade-off between security and usability. For example, developers often uninstall a preview OS version to return to a prior OS version. Increasing version numbers could prevent rolling back to a prior OS or could prevent returning your device to its factory settings. The Android Security team has determined that the lack of an incremented version number is a security issue, and is investigating possible solutions that preserve usability while addressing the risks raised by this report. At this time, the Android Security team is not aware of any way to exploit the reported vulnerability without an unlocked bootloader or an exploit chain through a separate vulnerability."
Jun 5 2017,
Jul 22 2017,
Sign in to add a comment