Skip to content

Win32k Window Object Type Confusion (CVE-2021-1732)

xxxCreateWindowEx sırasındaki bir user-mode callback'in, bir window'un extra-bytes storage mode'unu ve flag'ini birbiriyle uyumsuz bıraktığı bir win32kfull LPE; kernel bir offset'i pointer sanıyor ve sonuç OOB write -> arbitrary R/W -> SYSTEM oluyor.

Mechanism

Bug sınıfı: user-mode callback boyunca flag/type desync

Bir window object (tagWND), class'ına ait "extra bytes" değerini iki modda saklayabilir:

  • Mode 1 — buffer user-space heap'te tutulur ve raw pointer tagWND.pExtraBytes içinde durur.
  • Mode 2 — buffer kernel desktop heap'tedir (NtUserConsoleControl tarafından kurulur); burada pExtraBytes, desktop heap'e bir offset tutar ve bir extraFlag bit'i bunun offset tabanlı olduğunu işaretler.

xxxCreateWindowEx sırasında win32k, xxxClientAllocWindowClassExtraBytes üzerinden user mode'a geri çağrı (callback) yapar. Güvenlik açığı şu: bir saldırgan tam o callback'in içinde window'u Mode 1'den Mode 2'ye geçirebilir (offset flag'ini set eder) ve NtCallbackReturn üzerinden arbitrary bir değer döndürebilir. Kernel kaldığı yerden devam ettiğinde bu arbitrary değeri pExtraBytes'a az önce set edilen flag'i temizlemeden yazar — yani field artık saldırganın seçtiği bir sayıdır ve kernel bunu daha sonra güvenilir bir desktop-heap offset'i olarak yorumlar. Data değeri ile type flag'i uyumsuzdur: bir offset, pointer'a benzer bir miktarmış gibi karıştırılır ve bu da desktop heap içindeki (ve ötesindeki) memory safety'yi kırar.

Walkthrough

Yüksek seviyede; public root-cause analizlerinden (Project Zero ITW, DBAppSecurity/iamelli0t). 2021 başında BITTER APT tarafından in the wild exploit edildi.

  1. Callback'i hook'la: PEB.KernelCallbackTable üzerinden xxxClientAllocWindowClassExtraBytes slot'unu yönlendir ki window oluşturma sırasında saldırgan kodu çalışsın.
  2. Flag'i desync et: hook'un içinde NtUserConsoleControl çağırarak offset-mode flag'ini set et, ardından NtCallbackReturn ile kontrollü bir değer döndür. Kernel değeri commit eder ama flag'i set bırakır.
  3. OOB write: oluşan confusion'ı kullanarak komşu bir window'un cbWndExtra (extra-bytes uzunluğu) değerini büyük bir sayıyla overwrite et; böylece o window artık gerçek sınırlarının çok ötesine read/write yapabilir.
  4. Arbitrary read: victim window'un menu pointer'ını (spMenu) bozarak GetMenuBarInfo üzerinden kernel memory'sini parça parça oku.
  5. Arbitrary write: aşırı uzun extra bytes üzerinden SetWindowLongPtr kullanarak kontrollü write'lar yap.
  6. Privesc: EPROCESS/token adreslerini leak et ve SYSTEM process token'ını exploit eden process'in token'ının üzerine kopyala.

CVE-2022-21882 olarak yeniden ortaya çıktı

Aynı callback/flag desync pattern'i, orijinal fix'ten sonra CVE-2022-21882 olarak geri döndü; bu da altta yatan sınıfın tek bir offset kontrolü değil, user-mode-callback re-entrancy olduğunu vurguluyor.

Detection

  • Bir process'in kendi PEB.KernelCallbackTable'ına anormal write'lar veya user32.dll dışına işaret eden callback entry'leri.
  • Bir window-creation callback'inin içinden çağrılan NtUserConsoleControl, üstelik büyük/sıra dışı değerler döndüren NtCallbackReturn ile birlikte.
  • İmza niteliğindeki primitive zinciri: bir window'un cbWndExtra değerinin devasa bir sayıya şişmesi, ardından düşük yetkili bir process'ten beklenmedik handle'lara karşı GetMenuBarInfo read'leri ve SetWindowLongPtr write'ları.
  • Post-exploitation: az önce yoğun USER32 window aktivitesi yapmış bir process'in integrity/token elevation'ı.

Mitigation

  • CVE-2021-1732 (Şubat 2021) ve CVE-2022-21882 (Ocak 2022) için patch uygula. Fix, callback öncesi state'e güvenmek yerine extra-bytes storage mode'unu callback'ten sonra yeniden doğruluyor.
  • GDI/USER'a ihtiyaç duymayan process'ler için Win32k system-call filtering'i etkinleştir ki callback ile erişilebilen yüzey ortadan kalksın.
  • Defence-in-depth: HVCI/VBS, SMEP/SMAP ve Credential Guard, ortaya çıkan kernel R/W ile token-theft adımının değerini düşürür.

References

See also