Skip to content

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.)

  1. Trigger. kalloc.16 context'ini allocate etmek ve iki kez free etmek için race etmek üzere bir thread'de lio_listio()'yu loop'ta çağır.
  2. Reclaim. iosurface-property-spray üzerinden kalloc.16'yı spray et — iOS 13'te free edilmiş slot, tanınabilir magic value'lar (örn. 0x4141…) taşıyan OSData buffer'larıyla reclaim edilir; örtüşen allocation'ların tanımlanabilmesi için unique key'lerle bağlanmıştır.
  3. 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).
  4. 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'lu lio_listio() çağrıları ve büyük IOSurface/OSData property spray'leri, davranışsal imzadır.
  • Panic / zone-corruption log'ları. kalloc.16 double-free'si, freelist corruption ya da zone_require panic'leri olarak yüzeye çıkar; cihaz panic log'larını topla.
  • Anormal Mach port'ları. Post-fix zone/zone_require validation'ı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_issued accounting'i ve bir free_context flag'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-type kalloc.16 reclaim'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.

References