EPROCESS info disclosure (CVE-2021-31955)¶
ntoskrnl.exe'nin SuperFetch işlemesinde bir information-disclosure bug'ı:SuperfetchPrivSourceQueryclass'ıylaNtQuerySystemInformation(SystemSuperfetchInformation), unprivileged caller'lara kernelEPROCESSadresleri döndürür; KASLR'ı kırar ve process security token'ını bulur.
Mechanism¶
Invariant: bir SuperFetch query class'ı ham kernel pointer'ları redaction olmadan döndürür
NtQuerySystemInformation, geniş bir kernel "system information" class ailesine açılan
belgelenmemiş user-mode entry point'idir. Bunlardan biri, SystemSuperfetchInformation
(class 79), SuperFetch / sysmain'in memory-manager state'ini introspect etmek için
kullandığı arayüzdür. İçinde bir SUPERFETCH_INFORMATION header'ı ile seçilen
sub-query'ler vardır; burada ilgili sub-class SuperfetchPrivSourceQuery'dir.
İhlal edilen invariant, user/kernel sınırı boyunca kernel-pointer gizliliğidir. Windows
normalde kernel virtual adreslerini low-integrity / non-admin caller'lara döndürülen
structure'lardan uzak tutmaya özen gösterir, çünkü tam olarak bu adresler KASLR'ı
(kernel ASLR) bypass etmenin tohumudur. Ama SuperfetchPrivSourceQuery sonucu izlenen her
memory source için bir "private source" entry'si kaydeder ve process-backed source'lar
için bu entry, sahip olan EPROCESS object'inin kernel adresini gömer. Kaspersky'nin
in-the-wild PuzzleMaker chain analizinde dediği gibi:
"data returned by the
NtQuerySystemInformationfunction for the SuperFetch information classSuperfetchPrivSourceQuerycontains EPROCESS kernel addresses for currently executed processes."
Özel bir privilege gerekmez, dolayısıyla herhangi bir sandbox'lı process (örn. ele
geçirilmiş bir renderer) keyfi çalışan process'lerin — kendisi ve System process'i dahil
— EPROCESS pointer'ını okuyabilir. Geçerli bir kernel object adresi bir kez bilindiğinde
attacker'ın non-paged pool / process space'inde sabit bir anchor'ı olur: relative
offset'ler process Token pointer'ına (klasik token-stealing hedefi) ulaşır, ve ayrı
bir write primitive ile birleştiğinde KTHREAD'deki PreviousMode byte'ına. CWE-200:
hassas bilginin yetkisiz bir aktöre ifşası.
Walkthrough¶
Bu bug, vahşi doğada PuzzleMaker chain'inin info-leak aşaması olarak kullanıldı (CVE-2021-31956 NTFS pool overflow'u ile eşleştirilerek). Aşağıdaki akış kavramsaldır ve yalnızca yetkili araştırma / detection engineering içindir.
Bu bir leak'tir, write değil
CVE-2021-31955 tek başına hiçbir memory corruption vermez. Bir chain'in KASLR-defeat / object-locator yarısıdır; ikinci bir primitive (PuzzleMaker'daki NTFS overflow'u) aslında yetkileri çeviren kernel write'ını sağlar.
- SuperFetch query'sini gönder. Caller,
SuperfetchPrivSourceQuery'yi seçen birSUPERFETCH_INFORMATIONheader'ı doldurur ve native API'yi doğrudan çağırır:
// Undocumented; resolved from ntdll. Class 79 == SystemSuperfetchInformation.
typedef NTSTATUS (NTAPI *PNtQuerySystemInformation)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);
SUPERFETCH_INFORMATION info = {0};
info.Version = SUPERFETCH_VERSION; // expected version stamp
info.Magic = SUPERFETCH_MAGIC;
info.InfoClass = SuperfetchPrivSourceQuery;
info.Data = privSourceBuffer; // receives PF_PRIVSOURCE_QUERY_REQUEST entries
info.Length = sizeof(privSourceBuffer);
NtQuerySystemInformation(/*SystemSuperfetchInformation*/79,
&info, sizeof(info), &retLen);
Beklenen sonuç: STATUS_SUCCESS ve source başına kayıtlardan oluşan bir buffer.
- Dönen private-source kayıtlarını parse et. Process-backed source'lar için kayıt, ilgili
EPROCESS'in kernel virtual adresini taşır. İlgilendiğin source/PID üzerinde eşleştir (kendi process'in, ya daSystem= PID 4) ve onunEPROCESSpointer'ını oku.
[+] SuperfetchPrivSourceQuery returned N sources
[+] EPROCESS(self) = 0xffff...
[+] EPROCESS(System) = 0xffff...
- Leak edilen pointer'ı bir KASLR anchor'ı olarak kullan. Bilinen bir
EPROCESSbase'i ve build'e özgü field offset'leriyle şunların adresini hesaplayabilirsin: EPROCESS.Token(process_TOKEN'a giden_EX_FAST_REF) — token theft için, ve/veya-
PreviousModebyte'ına ulaşmak için sahip olanETHREAD/KTHREAD. -
Bir write primitive ile birleştir (PuzzleMaker'da CVE-2021-31956). İki belgelenmiş post-exploitation rotası:
- Token stealing: sandbox'lı process'in
Token_EX_FAST_REF'iniSystemprocess'in token pointer'ıyla overwrite et, SYSTEM haklarını miras al. - PreviousMode technique: bir thread'in
KTHREAD.PreviousMode'unu sıfırla, böylece o thread'den yapılanNtReadVirtualMemory/NtWriteVirtualMemoryKernelMode olarak ele alınır; bu, PuzzleMaker'ınSystemprocess'ine bir module enjekte etmek için kullandığı genel bir kernel read/write verir. Kaspersky, exploit'in düz token swapping yerine "nadiren kullanılan bir 'PreviousMode' tekniği kullandığını" not etti.
Bir EPROCESS leak'i neden bu kadar değerli
Tek bir meşru kernel object adresi, KASLR'ın dayandığı varsayımı kırar. Tek bir
EPROCESS'ten ActiveProcessLinks'i yürüyerek her process object'ini enumerate
edebilir, SYSTEM token'ına ulaşabilir ve kısıtlı bir write'ı tam bir SYSTEM privilege
escalation'a çevirebilirsin — ayrı bir KASLR brute-force'una ya da side channel'a gerek
kalmadan.
Detection¶
SystemInformationClass == SystemSuperfetchInformation (79)veSuperfetchPrivSourceQuerysub-class'ı ileNtQuerySystemInformationçağıran non-system, low-integrity process'ler oldukça şüphelidir — meşru olarak burasısysmain/SuperFetch'in alanıdır.- Eşli tespitler: bir SuperFetch query'sinin hemen ardından NTFS / pool manipülasyonu, ya da
PreviousMode'u değişmiş bir thread'denNtReadVirtualMemory/NtWriteVirtualMemorygelmesi PuzzleMaker pattern'ine uyar.
Mitigation¶
- Microsoft, CVE-2021-31955'i Haziran 2021 Patch Tuesday güncellemesinde yamaladı; ntoskrnl
fix'ini uygula, böylece SuperFetch private-source sonuçları artık
EPROCESSadreslerini ifşa etmez. - Derinlemesine savunma: non-admin caller'lar için kernel-pointer redaction'ı ve bu tür chain'lerin write yarısını sertleştiren exploit mitigation'ları (HVCI, KDP).