Skip to content

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