Skip to content

Attacking Titan M with Only One Byte (CVE-2022-20233)

Titan M Keymaster handler'ında emulated fuzzing ile bulunan single-byte out-of-bounds write, full code execution'a ve StrongBox-protected key'lerin extraction'ına escalate edilir.

Mechanism

Note

Titan M, Google'ın Pixel telefonlarda gönderdiği (Pixel 3'ten beri) dedicated security chip'idir. Open-source Chrome EC framework'ünden türetilmiş hafif, task-based bir embedded OS çalıştırır; static bir memory layout'a sahiptir (klasik anlamda heap yoktur) ve eşzamanlı write+execute permission'larını yasaklayan bir MPU'su vardır. Application Processor (AP) onunla bir SPI mailbox üzerinden konuşur ve serialized command request'leri (Keymaster, Weaver, attestation vb.) gönderir.

CVE-2022-20233, Keymaster ImportKey request handler'ındaki bir out-of-bounds single byte write'ıdır. Handler KeyParameter tag'lerinin listesini parse ederken DIGEST tag'ini (0x20005) arar. Bulduğunda, attach edilmiş integer value'yu alır ve — bazı check'lerden sonra ama uygun bir upper-bound check olmadan — onu bir stack buffer'a offset olarak kullanır, oraya strb instruction'ı ile 1 sabitini yazar. Aşılan trust boundary AP-to-chip'tir: bir Keymaster request'ini kontrol eden bir attacker (yani Android tarafındaki kod) SPI mailbox üzerinden uzanıp security chip'in memory'sini corrupt eder. Offset attacker-influenced olduğundan, tek write byte'ı amaçlanan buffer'ın dışına düşebilir.

Bir byte'ın neden yeterli olduğu: ASLR'siz, static-layout bir cihazda bilinen bir target address güvenilir şekilde erişilebilirdir. "Least significant byte yalnızca 0x0, 0x2 veya 0x4 olabilir" kısıtı bile seçili bir pointer field'ı clobber etmek için yeterli özgürlük bırakır. Araştırmacılar primitive'i bir global structure'daki request-buffer pointer'ını yeniden yazmak için kullandılar, 1-byte write'ı controlled bir büyük overwrite'a, sonra da ROP ve code execution'a dönüştürdüler.

Walkthrough

Bug, emulation-based fuzzing ile keşfedildi: Unicorn mode'unda AFL++, Keymaster task'larını tek tek emulate ediyor ve libprotobuf-mutator ile protobuf-shaped mesajlar üretiyordu. Crash, bir ImportKey request'i handle edilirken bir Unicorn UC_ERR_WRITE_UNMAPPED olarak yüzeye çıktı — firmware unmapped memory'ye bir byte yazmaya çalıştı.

Kavramsal olarak, vulnerable parse loop şunu yapar:

// pseudo-code reconstructed from the writeup
for (each KeyParameter p in params) {
    if (p.tag == 0x20005 /* DIGEST */) {
        // checks omitted: no proper upper bound on p.integer
        stack_buffer[p.integer] = 1;   // strb -> 1-byte OOB write
    }
}

Quarkslab tarafından tarif edilen exploitation chain'i:

  1. SPI request-buffer pointer'ını redirect et. 0x1e21d offset'ine 0x01 yazmak Keymaster SPI data structure'ını değiştirir, böylece gelen request buffer adresi değişir (0x192c8'den 0x101c8'e taşındığı raporlanmış). Artık sonraki request byte'ları amaçlanan buffer yerine komşu memory'yi overwrite eder.
  2. Bir payload sahnele. 556-byte'lık bir payload, bir stack frame unwind edildiğinde kontrolü ele geçiren geçerli bir code address taşır (bir idle task'ın saved return pointer'ı overwrite edilir).
  3. ROP ile stack pivot. sub sp, #0x20; mov r4, r0; ldr r3,[r0]; add.w r5,r4,#0x70; ldr r3,[r3,#8]; blx r3 formundaki bir gadget, stack'i tamamen controlled memory'ye "tırmanmak" için kullanılır.
  4. Bir command handler'ı hijack et. DestroyAttestationIds command handler'ının adresi değiştirilir ve bir trampoline gadget execution'ı final ROP chain'ine pivot eder.
  5. Bir read primitive inşa et. Chain, attacker-chosen argument'larla memcpy çağırır, target memory'yi Keymaster SPI response buffer'ına kopyalar, böylece AP tarafından read back edilebilir.

Code execution ile araştırmacılar StrongBox-protected cryptographic key'leri (örn. BeginOperation'ı sürüp sonra memory'yi dump'layarak), boot ROM içeriklerini ve bootloader'dan geçirilen Root of Trust'ı exfiltrate ettiler. Impact'i bir test app'inden bir AES key extract edip veriyi offline decrypt ederek gösterdiler.

Kullanılan tooling
  • nosclient — Quarkslab'ın Titan M'e SPI interface üzerinden arbitrary komutlar göndermek için açık kaynak client'ı.
  • Chip log'larını okumak ve exploitation'ı confirm etmek için bir SuzyQable debug cable (ya da lehimlenmiş wire'lar) üzerinden UART console erişimi.

Warning

Yalnızca authorized research / CTF / defensive kullanım. Chain, belirli bir firmware sürümünün static, ASLR-free layout'una bağlıdır; yukarıdaki offset ve gadget cited writeup'tan gelir ve version-specific'tir.

Detection

  • Firmware version detection. En güvenilir pratik indicator patch level'dir: June 2022 öncesi Pixel Security Update'inde kalan Titan M firmware'i vulnerable'dır. Cihazın security patch level'ını (ro.build.version.security_patch) kontrol etmek, fielded bir fleet'te riski triage etmenin birincil yoludur.
  • Anomalous NOS/Keymaster traffic. Exploit, privileged bir Android context'inden SPI mailbox üzerinden malformed ImportKey request'leri (out-of-range DIGEST tag value'ları ile) gönderilmesini gerektirir; nosclient tarzı raw NOS command trafiği veya beklenmedik Keymaster tag pattern'leri host tarafında gözlemlenebilir bir işaret olabilir.
  • Chip fault / reset telemetry. Corrupting write'lar Titan M'de unmapped-memory fault'ları, task crash'leri veya reset'ler tetikleyebilir; UART console log'ları (SuzyQable üzerinden) ya da kernel'in gördüğü tekrarlayan NOS/citadel reset'leri, lab ortamında exploitation'ın bir belirtisidir.
  • Inherent limitation. Bir kez chip compromise edildiğinde host tarafından güvenilir detection/attestation zordur; bu yüzden birincil savunma detection değil, patching'dir (version detection + update).

Mitigation

Google CVE-2022-20233'ü (Critical olarak rated) June 2022 Pixel Security Update'inde patchledi. Spesifik key-exfiltration riski için, app'ler StrongBox key'lerinde setUserAuthenticationRequired(true) çağırabilir, böylece key kullanılmadan önce biometric/PIN authentication gerekir.

References