diff --git a/src/mobile-pentesting/android-app-pentesting/android-physical-attacks.md b/src/mobile-pentesting/android-app-pentesting/android-physical-attacks.md index a53b8d845b5..873969ff6ca 100644 --- a/src/mobile-pentesting/android-app-pentesting/android-physical-attacks.md +++ b/src/mobile-pentesting/android-app-pentesting/android-physical-attacks.md @@ -54,6 +54,51 @@ If you need the early-boot details for MediaTek devices, review: Also note that **public tooling such as [MTKClient](https://github.com/bkerler/mtkclient)** makes several MediaTek Boot ROM / download-mode workflows practical on affected chipsets. +### Biometric TA AuthToken forgery: root-to-CE bypass without patching Gatekeeper + +A second reusable pattern is to **abuse biometric Trusted Applications (fingerprint / face TAs) that share the same AuthToken HMAC trust domain as Gatekeeper and Keymaster / KeyMint**. On Android, a successful authenticator returns a signed **`hw_auth_token_t`** proving who authenticated, by which method, and when. If a biometric TA can be tricked into **signing attacker-controlled data** or **leaking the shared per-boot HMAC key**, Android root can be upgraded into **PIN recovery** and sometimes **BFU CE decryption**. + +Relevant AuthToken properties: + +- `hw_auth_token_t` is a fixed **69-byte** structure with fields such as `challenge`, `user_sid`, `authenticator_id`, `authenticator_type`, `timestamp`, and a trailing **32-byte HMAC-SHA256** computed with a **per-boot shared secret**. +- `authenticator_type = 1` is the important value for **Gatekeeper / PIN** tokens. +- Keymaster / KeyMint validates the HMAC, freshness, SID binding, and expected authenticator type before releasing authentication-bound key operations. + +Common exploitation patterns seen in vendor biometric TAs: + +1. **Signing oracle (`GET_AUTH_OBJ`-style bugs)**: a TA command accepts an arbitrary 69-byte buffer and simply HMAC-signs it, without checking that a fingerprint/face match actually happened. +2. **Biometric result oracle + verifier confusion**: a TA emits a valid **type-2** biometric token without a real match, and Keymaster incorrectly accepts it for operations that should require **type-1** Gatekeeper authentication. +3. **Error-path secret leakage**: HMAC verification failures print or return the shared **32-byte per-boot AuthToken HMAC key** via TrustZone logs, shared memory, or even `dmesg`-reachable secure logs. +4. **TA memory disclosure / corruption**: out-of-bounds reads or arbitrary-read primitives leak plaintext per-boot HMAC keys from heap / stack / BSS after defeating weak TA ASLR. + +Once the attacker can mint a valid **type-1** token (or a verifier incorrectly accepts **type-2**), the remaining CE attack looks very similar to the early-boot TEE-patching chain, but **without** modifying Gatekeeper itself: + +1. Obtain **Android root / kernel EL1 R/W**. +2. Invoke the biometric TA directly with **`libTEEC`** or an equivalent TEE client. +3. Forge or request a signed **Gatekeeper-typed AuthToken**. +4. Pass that token to **Keymaster / KeyMint** to decrypt the first-stage **Synthetic Password** blob. +5. Brute-force the real PIN **offline** using the AES-GCM tag as a correctness oracle. + +Minimal attacker view: + +```python +at = forge_gatekeeper_authtoken() # type = 1, HMAC valid +spblob = read('/data/system_de//spblob/...') +intermediate = keymaster_decrypt(at, spblob) + +for pin in range(1_000_000): + key = derive_synthetic_pw(intermediate, pin) + if aes_gcm_decrypt(intermediate, key): + return pin +``` + +Operational notes: + +- **BFU impact** usually requires a forged **type-1 / Gatekeeper** token that Keymaster accepts before first unlock. +- **AFU-only** cases can still exist if the device incorrectly accepts biometric **type-2** tokens after first unlock. +- Multiple dormant fingerprint TAs in one firmware image increase attack surface because **each TA may hold the same per-boot AuthToken HMAC material**. +- **StrongBox / Weaver-backed** designs reduce the usefulness of this chain because recovering the Keymaster-gated intermediate is not always enough to obtain an offline brute-force oracle. + ### StrongBox / Weaver changes the brute-force model If the device uses **Weaver** backed by a separate Secure Element / StrongBox, compromising Android or even the TEE is usually **not enough** to obtain an offline brute-force primitive: @@ -88,8 +133,12 @@ For defenders and app testers, the important lesson is simple: **if the target d ## References - [Demystifying phone unlocking tools: A technical overview](https://osservatorionessuno.org/blog/2026/05/demystifying-phone-unlocking-tools-a-technical-overview/) +- [Android Open Source Project - Authentication](https://source.android.com/docs/security/features/authentication) +- [Android Open Source Project - Gatekeeper](https://source.android.com/docs/security/features/authentication/gatekeeper) - [Android Open Source Project - Weaver](https://source.android.com/docs/security/features/authentication/weaver) +- [Android Open Source Project - KeyMint implementer reference](https://source.android.com/docs/security/features/keystore/implementer-ref) - [MTKClient](https://github.com/bkerler/mtkclient) +- [The Biometric AuthToken Heist: Forging Android AuthTokens from Biometric Trusted Applications](https://darknavy.org/blog/the_biometric_authtoken_heist) - [First analysis of Apple's USB Restricted Mode bypass (CVE-2025-24200)](https://blog.quarkslab.com/first-analysis-of-apples-usb-restricted-mode-bypass-cve-2025-24200.html) {{#include ../../banners/hacktricks-training.md}}