physmap Spraying¶
Saldıran process'in address space'ini bir payload'ın birçok kopyasıyla doldur; böylece kernel'in 1:1 direct map'i (physmap), o payload'ı tahmin edilebilir bir kernel-virtual adreste tutmuş olması garanti edilir — ret2dir'in arkasındaki address-aliasing primitive'i, SMEP/SMAP/KERNEXEC'i atlatan.
Mechanism¶
Neden çalışır
Performans için Linux kernel'i physmap'i (direct map) tutar: fiziksel
RAM'in bir kısmını veya tamamını 1:1 map'leyen büyük, bitişik bir
kernel-virtual bölge. x86-64'te 0xffff888000000000'dan başlayarak 64 TB'a
kadar kapsar; page frame'lerini frame sıfırdan yukarı doğru map'ler. Sonuç
olarak fiziksel belleğin her page'inin (en az) iki virtual alias'ı vardır —
sahip process'in gördüğü userland mapping'i ve kernel'de yerleşik physmap
synonym'i. Bu address aliasing tüm hilenin kendisidir: bir user
process'in kendi page'ine yazdığı veri, aynı anda bir kernel adresi
üzerinden okunabilir/execute edilebilir.
Eğer saldırgan bir user page'inin page frame number'ını (PFN) leak edebilirse —
örn. /proc/self/pagemap üzerinden — synonym doğrudan hesaplanır:
PFN(uaddr) = pagemap[uaddr] & 0x7fffffffffffff # bits [0:54]
SYN(uaddr) = PHYS_OFFSET + PAGE_SIZE * (PFN - PFN_MIN)
Burada PFN_MIN, physmap'in map'lediği ilk RAM frame'idir (RAM'in fiziksel
base'i). Fiziksel belleğin adres 0'dan başladığı standart x86-64'te
PFN_MIN = 0'dır ve formül kernel'in kullandığı basit lineer forma —
SYN = PHYS_OFFSET + (PFN << PAGE_SHIFT) — indirgenir. Çıkarma terimi
yalnızca RAM base'inin sıfırdan farklı olduğu platformlarda (ör. bazı ARM
SoC'ler) bu offset'i telafi etmek için gerekir; ret2dir formülasyonunun
architecture-independent hali budur.
PFN leak'i mevcut olmadığında, spraying olasılığı güvenilirliğe çevirir: saldırgan önceden keyfi, sabit bir physmap adresi seçer ve sonra kendi address space'ini payload'ın o kadar çok kopyasıyla doldurur ki, seçilen o kernel adresini destekleyen page frame'inin payload page'lerinden biri olması ezici bir olasılıkla mümkün hale gelir. Suistimal edilen invariant basitçe şudur: physmap tüm RAM'i kapsar, dolayısıyla RAM'i payload ile sel altında bırakmak, hedef physmap slot'unun payload tutmasını garanti eder.
Walkthrough¶
Bu, ret2dir için bir teknik-yapı taşıdır: user kontrolündeki bir payload'ın kernel'de yerleşik bir kopyasını tahmin edilebilir bir adreste üretir. Aşağıdaki adımlar yalnızca spraying yarısıdır.
1. Payload page'ini oluştur. Kernel control-flow hijack'in daha sonra atlayacağı veya dereference edeceği fake object'i, ROP chain'i veya shellcode'u içeren page-boyutunda bir buffer.
2. Onu address space'e spray et. Tekrar tekrar anonim page'leri mmap edin ve
payload'ı her birine kopyalayın; böylece fiziksel RAM'in büyük bir kısmı payload
olur:
#define SPRAY_PAGES (16 * 1024)
void *physmap_spray[SPRAY_PAGES];
for (int i = 0; i < SPRAY_PAGES; i++) {
void *mp = mmap(NULL, 4096,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
memcpy(mp, payload, 0x500); /* copy of the payload */
physmap_spray[i] = mp;
}
Her page'e dokunmak (memcpy), buddy allocator'ı gerçekten page frame'leri
dağıtmaya zorlar; payload'ı fiziksel bellek boyunca ve dolayısıyla physmap boyunca
maddeleştirir.
3. Sabit bir physmap adresini hedefle. Spray'in nereye düştüğünü keşfetmek yerine, saldırgan seçilmiş bir physmap adresini (direct-map aralığı içinde, çok büyük olasılıkla RAM ile desteklenen bir değer) hard-code eder ve onu kernel control-flow hedefi olarak kullanır:
/* attacker-chosen direct-map address expected to hold a payload copy */
unsigned long target = 0xffff888000000000UL + CHOSEN_OFFSET;
Spraying'den sonra, o adres yüksek olasılıkla payload page'lerinden birini alias'lar; böylece kernel, saldırgan byte'larını sabit bir kernel-virtual adreste görür.
Spraying istatistikseldir
Spraying, kesin bir PFN leak'ini bir olasılıkla takas eder. Güvenilirlik, saldırganın ne kadar RAM doldurabildiğine karşı toplam RAM'e ve diğer kiracıların allocation'larına bağlıdır; seçilen page'i pin'lemek (swap/reclaim'den kaçınmak) ve yeniden denemek başarıyı artırır. Pagemap üzerinden gerçek bir PFN leak ile tahmin kesin hale gelir.
Detection¶
Davranış göze çarpar: binlerce anonim page'i mmap edip hepsine hemen özdeş
payload byte'ları yazan bir process, güçlü bir heap/page-spray sinyalidir.
/proc/<pid>/pagemap PFN bitlerini unprivileged kullanıcılara kısıtlamak,
precise-aliasing oracle'ını kaldırır ve daha gürültülü spraying yolunu zorunlu
kılar.
proc-pid-pagemap-physical-address-leak'a
bakın.
Mitigation¶
Yapısal düzeltme, alias'ın kendisini kırmaktır. Exclusive Page Frame Ownership (XPFO) — ret2dir ile birlikte önerilmiştir — bir page frame'i userspace'e ait olduğu sürece physmap'ten unmap eder ve kernel alias'ını yalnızca frame kernel'e döndüğünde geri yükler; böylece payload'ın hedefleyecek bir kernel-virtual synonym'i basitçe yoktur. Payload kernel belleğinde yaşadığı için, user/kernel sınırına göre key'lenen data-access ve execution savunmaları — SMEP, SMAP, PaX KERNEXEC/UDEREF — physmap spraying'i durdurmaz; CPU meşru bir kernel adresi görür.
References¶
- Kemerlis, Polychronakis, Keromytis. ret2dir: Rethinking Kernel Isolation (USENIX Security 2014). — https://www.usenix.org/system/files/conference/usenixsecurity14/sec14-paper-kemerlis.pdf
- Kemerlis. ret2dir: Deconstructing Kernel Isolation (Black Hat EU 2014). — https://www.blackhat.com/docs/eu-14/materials/eu-14-Kemerlis-Ret2dir-Deconstructing-Kernel-Isolation-wp.pdf
- Fernweh. Linux Kernel PWN | 05 ret2dir (physmap spraying walkthrough). — https://blog.wohin.me/posts/linux-kernel-pwn-05/