Win32k NtUserMessageCall pool UAF (MS15-061)¶
xxxSetClassLong/ message-dispatch path'inde user-mode callback etrafında eksik bir window-class lock yüzünden oluşan bir win32k.sys use-after-free; aynı aile (CVE-2015-2360) Duqu 2.0 malware platformu tarafından local privilege escalation için kullanıldı.
Mechanism¶
Note
win32k, callback'ler aracılığıyla tekrar tekrar user mode'a geçiş yapar (win32k'nın başlangıçta user mode'da çalışmış olmasının bir kalıntısı). Güvenlik invariant'ı şudur: bir callback'ten sonra hâlâ ihtiyaç duyulan herhangi bir kernel object, o callback boyunca reference-locked olmalıdır.
MS15-061, user-mode callback'leri önce window kernel class object'ini lock'lamadan çağıran bir dizi class-data routine'ini (xxxSetClassLong ve ilgili xxxSetClassData → xxxSetClassCursor → xxxSetClassIcon zinciri) kapsar. Callback sırasında, bu path'lere NtUserMessageCall / xxxSendMessage gibi window-message dispatch üzerinden ulaşan bir attacker, class'ı veya ilişkili object'i destroy eder. Kernel kaldığı yerden devam eder ve free edilmiş pool memory üzerinde işlem yapar: kernel pool'da bir use-after-free.
Free edilmiş allocation, dangling use'tan önce attacker'ın şekillendirdiği data ile reclaim edilebildiği için, UAF bir crash olmaktan çıkıp kontrollü bir corruption primitive'ine dönüşür ve NT AUTHORITY\SYSTEM'a yükselir.
Vulnerability class
Bu bug bir use-after-free'dir (freed pool memory'e erişim), lineer bir pool buffer overflow (adjacent chunk'lara out-of-bounds write) değildir. Bazı eski adlandırmalar (bu sayfanın slug'ı dahil) pool-overflow terimini kullansa da doğru sınıf — title ve body'de olduğu gibi — kernel pool UAF'tir.
Walkthrough¶
NCC Group MS15-061 writeup'ına dayanan kavramsal bir reproduction. Yalnızca mantıksal adımlar.
Warning
Defender'lar için uzun süre önce patch'lenmiş (Haziran 2015) bir bug'ın taslağı. Pool offset, tag veya weaponize edilmiş sequence yok.
Step 1 — Lock'suz callback path'ine ulaşın.
Window-message dispatch'i (NtUserMessageCall / xxxSendMessage ailesi üzerinden), class object'ini lock'lamadan user-mode callback yapan bir class-data update'ine (xxxSetClassLong ve benzerleri) doğru sürün.
Step 2 — Callback sırasında free edin. User-mode callback'ten, window'u veya class'ı destroy edin; böylece onu backing eden pool allocation, kernel hâlâ ona bir reference tutarken free edilir.
Step 3 — Free edilmiş pool block'unu reclaim edin. Free edilen block'un attacker data ile yeniden işgal edilmesi için eşleşen boyutta kontrollü allocation'lar spray edin. Bkz. heap grooming / feng shui ve kernel Low Fragmentation Heap exploitation.
Step 4 — Dangling use bir primitive'e dönüşür. Kernel kaldığı yerden devam eder ve free edilip sonra reclaim edilen object'i dereference eder; bu attacker'a kontrollü bir write (ve oradan da read/write) verir. Bkz. use-after-free.
Step 5 — Privilege escalation.
Kernel read/write, bir token swap gerçekleştirmek için kullanılır; mevcut process token'ı SYSTEM token'ı ile değiştirilir. Bu, Duqu 2.0 platformunda (CVE-2015-2360) gözlemlenen LPE aşamasıdır.
Detection¶
- Anormal message-dispatch sıralaması. Untrusted bir process'ten message callback'leri üzerinden çağrılan class-data update'leri (
SetClassLong*), object destruction callback'in içinde gerçekleşiyorsa. win32k.syspool bugcheck'leri (ör. pool corruption / special-pool fault'ları), class-handling routine'lerine referans veriyorsa başarısız bir exploitation'a işaret eder; UAF'yi deterministik olarak ortaya çıkarmak için test ortamlarında win32k üzerinde Special Pool / Driver Verifier'ı etkinleştirin.- Kernel pool spray göstergeleri. Bir class-data callback'ini tetikledikten hemen sonra bir GUI process'ten gelen aynı boyutta kernel allocation patlamaları.
- Threat-intel korelasyonu. Duqu 2.0 bu LPE'yi gizli, memory-resident bir toolkit içinde kullandı; host sinyallerini Kaspersky'nin Duqu 2.0 indicator'ları ile eşleştirin.
Mitigation¶
- MS15-061'i uygulayın (9 Haziran 2015). Fix, etkilenen
xxxSetClass*callback'lerinin etrafına açık bir class lock/unlock ekler; böylece class object, user-mode transition sırasında free edilemez. - Win32k syscall filtering, GUI syscall'larına ihtiyaç duymayan process'ler için bu path'lerin erişilebilirliğini ortadan kaldırır. Bkz. Disable Win32k system calls.
- Driver Verifier / Special Pool, test/hunt ortamlarında win32k üzerinde sessiz UAF'leri anında, atfedilebilir bugcheck'lere dönüştürür.
- Defense in depth. Güncel platformlar (bu bug, mevcut win32k hardening'inden öncedir), credential-theft monitoring ve least-privilege, son token-swap aşamasının etkisini sınırlar.