tachy0n / unc0ver (LightSpeed)¶
LightSpeed'i geri getiren regression: CVE-2020-9859, XNU
lio_listio()'da bir double-free; unc0ver 5.0.0'da (iOS 13.0–13.5) bir 0-day olarak yayınlandı, Apple tarafından iOS 13.5.1'de patch'lendi.
Mechanism¶
Note
Bug class: spice-treadm1ll (LightSpeed) ile aynı lio_listio() aio_lio_context double-free'i, iOS 13'te bir regression olarak yeniden ortaya çıktı. CVE-2020-9859 — Apple bunu improved memory handling ile ele alınan bir memory-consumption sorunu olarak tanımladı; CERT/CC bunu lio_listio()'da bir double-free olarak izler.
Asıl içgörü yeni bir bug değil, tarihtir:
- iOS 12, orijinal LightSpeed'i (CVE-2018-4344) patch'ledi ama root cause'u düzeltmedi ve bir memory leak bıraktı.
- iOS 13 o leak'i düzeltti — ve bunu yaparken eski vulnerable davranışa geri döndü. Orijinal LightSpeed PoC'si iOS 13'te yeniden tetiklenir. Bu bir regression'dır (başarısız cross-branch patch bakımı), bir variant değil.
İhlal edilen invariant aynıdır: lio_listio() ve onun async worker thread'leri, kalloc.16 boyutundaki aio_lio_context'i kimin free edeceği konusunda anlaşamaz. Hata koşulları altında (NULL entry'ler, LIO_NOP, request limitlerini aşma), "issued" işlemlerin accounting'i yanlıştır, dolayısıyla syscall bir worker'ın zaten free ettiği bir context'i free eder — attacker spray'iyle reclaim edilebilen bir double-free. Slot'u controlled byte'larla reclaim etmek bir fake Mach port verir ve oradan fake bir kernel-task-port.
Walkthrough¶
(High-level, Siguza'nın tachy0n writeup'ına ve Project Zero taramasına göre.)
- Trigger.
kalloc.16context'ini allocate etmek ve iki kez free etmek için race etmek üzere bir thread'delio_listio()'yu loop'ta çağır. - Reclaim. iosurface-property-spray üzerinden
kalloc.16'yı spray et — iOS 13'te free edilmiş slot, tanınabilir magic value'lar (örn.0x4141…) taşıyanOSDatabuffer'larıyla reclaim edilir; örtüşen allocation'ların tanımlanabilmesi için unique key'lerle bağlanmıştır. - Overlap. Aynı kernel belleği üzerinde örtüşen
OSData/OOL-descriptor object'leri oluştur; birini free et ve controlled fake-port/task içeriği kurmak için OOL Mach-port descriptor'larını yeniden spray et (bkz. fake-mach-port-fakeport). - Leak + R/W. Controlled descriptor içeriğinden kernel adreslerini kurtar ve bir kernel read/write primitive'i kur, sonra fake bir kernel task port forge et.
Warning
Sevk edilen exploit, ayrıca page header'larını formatlayarak — zone_map dışı bir page'in check'i geçmesini sağlayarak — dönemin zone_require mitigation'ını da aştı; bu da kaba bir zone check'inin gerçek allocator isolation'ının yerini tutmadığını gösterir.
Neden önemliydi
tachy0n, o sıralar güncel olan iOS'ta bir 0-day olarak unc0ver 5.0.0'da (2020-05-23) sevk edildi. Apple iOS 13.5.1'i yalnızca günler sonra sevk etti (kernel build tarihi 2020-05-26).
Detection¶
lio_listio()storm + IOSurface spray. Untrusted bir app'ten Mach trafiğine race eden ağır loop'lulio_listio()çağrıları ve büyükIOSurface/OSDataproperty spray'leri, davranışsal imzadır.- Panic / zone-corruption log'ları.
kalloc.16double-free'si, freelist corruption ya dazone_requirepanic'leri olarak yüzeye çıkar; cihaz panic log'larını topla. - Anormal Mach port'ları. Post-fix zone/
zone_requirevalidation'ında başarısız olan bellekle desteklenen port'lar, fake-port inşasına işaret eder.
Mitigation¶
- Apple'ın iOS 13.5.1 patch'i. Cleanup path'ini açık
io_issuedaccounting'i ve birfree_contextflag'iyle yeniden düzenler, böylece syscall context'i yalnızca hiç I/O dispatch edilmediğinde free eder; iş kuyruğa alındığında onu yalnızca worker free eder. - kheap separation, zone sequestering, PAC, signed
ipc_kmsg(iOS 14+). Cross-typekalloc.16reclaim'ini kırar ve fake-port forgery'sinin çıtasını yükseltir. - Cihazları güncel tut. Bir regression olarak ders patch-hijyenidir: forklanmış kernel branch'leri boyunca regression test'lerini zorla; kullanıcılar patch'li iOS'ta kalmalıdır.