EntryBleed KPTI KASLR bypass (CVE-2022-4543)¶
KPTI, syscall/interrupt entry text'ini user page table'da map'li tutmak zorundadır; bir prefetch timing side channel'ı bu KASLR-randomize edilmiş entry mapping'ini bulur ve KPTI altında bile kernel base'ini sızdırır.
Mechanism¶
Note
KPTI (Kernel Page Table Isolation), yani Meltdown mitigation'ı, kernel sayfalarını user
page table'dan unmap eder — ama syscall/interrupt entry text'ini unmap edemez, çünkü
CPU CR3'ü user'dan kernel page table'a geçirmek için o kodu çalıştırmak zorundadır. Yani
entry_SYSCALL_64, user page table'da KASLR-rebase edilmiş adresinde map'li kalır ve
page-table entry'sinin global bit'i set olduğundan TLB entry'si CR3 write'larından sağ çıkar.
Bir prefetch instruction'ı, bir virtual address'in translate edilebilir olup olmadığını
timing yoluyla sızdırır: zaten TLB'de olan bir adrese yapılan prefetch hızlı tamamlanır;
unmapped bir adrese yapılan ise daha yavaştır (bir page walk tetikler/yarıda bırakır) —
Gruss vd.'nin "Prefetch Side-Channel Attacks" primitive'i. iTLB'yi bir syscall ile
primlemek, sonra aday kernel adreslerini prefetch ile probe etmek, hangisinin canlı entry
mapping'i olduğunu açığa çıkarır. Kernel base = leaked_address - entry_SYSCALL_64_offset.
Red Hat: "Intel sistemleri için herhangi bir local attacker'ın TLB timing'ine dayalı
prefetch side channel'larıyla KASLR base'ini kolayca, hızlıca ve güvenilir şekilde
sızdırması."
Walkthrough¶
Probe, serialize edilmiş RDTSC ile bir prefetch'i zamanlar ve minimum-latency'li adresi seçer:
mfence; rdtscp ; time A
lfence
prefetchnta [addr]
prefetcht2 [addr]
lfence
rdtscp ; time B
mfence
delta = B - A ; small delta => TLB hit => mapped entry
Tarama yapısı (willsroot.io writeup'ından):
- Arama penceresi
0xffffffff80000000..0xffffffffc0000000,0x200000adımlarla. - Aday başına ~5 warmup iteration, sonra 100+ ölçüm; adres başına timing'i biriktir.
- Minimum ortalama latency'ye sahip adres entry mapping'idir; kernel base'ini elde etmek
için kernel'a özgü
entry_SYSCALL_64offset'ini çıkar.
Warning
x86-64 kernel image'ı 2 MB sınırında map'lenir (0x200000, ~9 bit text entropy'si), yani
sadece ~512 hizalı slot test edilmesi gerekir. entry_SYSCALL_64 offset'i
kernel-version'a bağlıdır (örnek olarak 0x400000 raporlandı ama hedef başına türetilmeli
— hardcode etme). Intel'de ve KVM -cpu host içinde çalışır; bir saniyenin altında
de-randomize eder. CVE-2022-4543, CVSS 5.5.
Detection¶
Kernel-range adresleri üzerinde yüksek-frekanslı prefetch+rdtscp döngüleri alışılmadık,
tespit edilebilir bir pattern'dir, ama teknik yalnızca unprivileged instruction'lar kullanır
ve kernel tarafında hiçbir iz bırakmaz.
Mitigation¶
Basit bir flush bunu düzeltmez. Writeup, user-mapped entry/exit handler'larının virtual address'ini kernel base'inden bağımsız randomize etmeyi, ya da onları KASLR ile ilgisiz sabit bir adrese yerleştirmeyi önerir. High-resolution timer'ları kısıtlamak çıtayı yükseltir ama kanalı kapatmaz.