Skip to content

v0rtex (CVE-2017-13861)

Siguza'nın IOSurface Mach-port over-release UAF'i; bir IOSurface property spray ile fake bir port'a yeniden allocate edilip iOS 10.x ve öncesinde kernel R/W ve tfp0'a ulaşır.

Mechanism

Note

IOSurfaceRootUserClient::s_set_surface_notify(), user-supplied bir Mach port üzerinde bir fazladan reference düşürür. Kırılan invariant, IPC port reference-count sözleşmesidir: userland handle, process bir right tuttuğu sürece port'u canlı tutmalıdır. Over-release, kernel'in ipc_port'u free etmesine izin verir; bu sırada hâlâ geçerli bir userland name, free edilmiş zone slot'unu göstermeye devam eder. O dangling-ama-isimli port, klasik bir Mach port use-after-free'dir: slot attacker byte'larıyla reclaim edildiğinde, kernel saldırganın kontrol ettiği bir yapıyı gerçek bir port'muş gibi parse eder.

Walkthrough

Üst düzey, Siguza'nın açık writeup'ından ve Project Zero anketinden. Yalnızca kavramsal aşamalar — offset ya da gadget yok.

  1. Groom ve spray. Hedef port'un port zone'un öngörülebilir bir bölgesinde oturması için geniş bir Mach port alanı allocate et (bkz. heap grooming / feng shui).
  2. Over-release. Fazladan reference'ı düşürmek için vulnerable IOSurface notify yolunu çağır; bir userland name hâlâ ona referans verirken hedef ipc_port'u free et.
  3. Komşuları free et + GC'yi zorla. Page üzerindeki çevredeki port'ları free et, sonra zone garbage collection'ı (mach_zone_force_gc) zorla ki free edilmiş page farklı bir zone tarafından yeniden kullanılmak üzere geri salınsın.
  4. IOSurface property spray ile reclaim. Değerleri doğru boyutta OSString/OSData buffer'larına deserialize olan IOSurface property'lerini ayarlayarak page'i yeniden allocate et, free edilmiş slot'u kontrollü bir byte deseniyle doldur — bir fake Mach port. Bkz. iosurface-property-spray.
  5. Fake port'u retype ederek primitive'ler kur. Writeup, fake port'u ardışık ip_kotype değerleri boyunca dolaştırır: örn. KASLR'ı brute-force etmek için bir clock port, sonra pid_for_task üzerinden dar read'ler için bir task port, ve nihayet bir kernel task port'a doğru.
  6. tfp0. Kararlı bir read ve kontrollü bir fake port ile, arbitrary kernel R/W veren bir kernel task port (task_for_pid(0)-eşdeğeri) kur — bkz. kernel-task-port.
Spray içeriği neden önemli

Reclaim object'i (a) free edilmiş ipc_port ile aynı allocation size class'ına inmeli ve (b) kernel'in minimal geçerli bir port olarak kabul edeceği bir byte layout içermelidir. IPC context gibi alanlar, herhangi bir tehlikeli işlem yapılmadan önce hangi spray'lenen buffer'ın dangling slot'a indiğini doğrulamak için bir side channel olarak kullanılır.

Detection

  • IOSurface user-client trafiği telemetrisi: async surface-notify yolunu büyük Mach-port allocation patlamalarıyla birlikte çağıran bir process, çoğu app için anormaldir.
  • Zorlanmış zone GC (mach_zone_force_gc), unprivileged bir app'ten nadirdir ve port spray ile korelasyonlandığında güçlü bir grooming sinyalidir.
  • Port-sayısı anomalileri: binlerce port tutan ve ardından toplu deallocation yapan bir process, reclaim grooming'i düşündürür.
  • Panic / Jetsam logları malformed fake port'lardan (yarı geçerli bir port'un teardown'ı), onları loglayan cihazlarda gürültülü bir post-failure göstergesidir.

Mitigation

  • iOS 11.2 / tvOS 11.2 / watchOS 4.2'de patch'lendi — IOSurface notify yolundaki fazladan port reference düşüşü düzeltildi; birincil mitigation budur.
  • zone_require / zone validation (sonraki XNU'da eklendi), bir object'in iddia ettiği zone'da yaşayıp yaşamadığını kontrol eder ve bir port slot'unu bir OSString ile cross-zone reclaim etmeyi kırar.
  • IPC object'leri üzerindeki reference-count saturation / range check'leri, free'den önce over-release'i tespit eder.
  • PAC ve PPL (sonraki A-serisi / iOS), fake-port R/W'yi kalıcı kernel-task kontrolüne çevirmenin maliyetini artırır. KASLR, herhangi bir pointer kullanılabilir olmadan önce leak adımını zorunlu kılar.

References