Skip to content

Info Leak / Pointer Leak ASLR Bypass

In-bounds tek bir pointer'ı leak etmek bir modülün, library'nin veya kernel image'ının base'ini açığa çıkarır ve ASLR/KASLR'yi yener, çünkü o nesne içindeki diğer her offset sabittir.

Mechanism

ASLR, bir modülün, shared library'nin, stack'in, heap'in veya kernel image'ının map'lendiği base'i randomize eder, ancak bu nesnelerin yerleşimini randomize etmez. Yüklü bir image içindeki fonksiyonların, global'lerin, vtable'ların ve gadget'ların göreli offset'leri link zamanında sabitlenir.

Invariant the bypass breaks

ASLR, attacker'ın hedefin address space'inde herhangi bir mutlak adresi bilmemesine dayanır. Bilinen bir nesnenin içinde yaşayan, leak edilmiş tek bir pointer bu varsayımı çökertir: nesne içindeki offset'ler sabit olduğundan, base = leaked_pointer - known_offset nesnenin base'ini kurtarır ve oradan o nesne içindeki her adresi. Randomization hiçbir brute force olmadan yenilir.

Pointer, bir format-string güvenlik açığı (%p/%x ile stack'i okuma), bir out-of-bounds read, eski (stale) bir pointer'ı yüzeye çıkaran bir uninitialized-memory read ya da bir memory-read primitive yaratan bozulmuş bir length/pointer alanı yoluyla açığa çıkarılabilir. Linux'ta kernel-pointer hardening (kptr_restrict, kallsyms restriction, hashed pointer'lar) tam da bu leak'leri /proc ve dmesg'den engellemek için vardır.

Walkthrough

Bu bir bypass tekniğidir. Adımlar:

  1. Bir read/disclosure primitive elde et. Örnekler: bir printf(user_input) format-string bug'ı, bir OOB array read'i ya da (browser exploit'lerinde olduğu gibi) script'ten erişilebilen bir arbitrary-read arayüzü kurmak için bir typed array'in buffer pointer'ını ve length'ini overwrite etmek.
  2. In-bounds bir pointer leak et. Hedef bir nesnenin içini gösterdiğini bildiğin bir değeri oku — örn. kaydedilmiş bir return address (main binary'nin içine), bir libc fonksiyon pointer'ı (libc'nin içine) ya da bir vtable pointer'ı (bir modülün içine). rh0dev write-up'ında, manipüle edilmiş bir typed-array header'ından bir vtable pointer'ı leak edilir ve ardından "herhangi bir import/export table'a dokunmadan" daha fazla bellek okumak için kullanılır.
  3. Base'i hesapla. O sembolün bilinen statik offset'ini leak edilen adresten çıkararak nesnenin randomize edilmiş load base'ini elde et.
  4. Geri kalan her şeyi türet. Artık bilinen image içindeki fonksiyonları (system, mprotect) ve ROP gadget'larını bulmak için sabit offset'ler ekle.
  5. Kodu yeniden kullan. Bilinen modüldeki "yalnızca gadget'lardan" oluşan bir ROP chain kur ve ASLR'nin yanı sıra DEP/NX'i de bypass et.
Format-string leak (userland)

$ ./vuln "%p %p %p %p %p %p"
0x7ffd... 0x7f9a3c4a1b40 (nil) 0x401136 ...
0x401136, main binary'nin .text'inde yer alır; o return site'ının binary'ye göreli offset'ini çıkarmak PIE base'ini verir. 0x7f9a3c4a1b40, libc'de yer alır; sembol offset'ini çıkarmak libc base'ini verir.

Warning

Leak edilmiş bir pointer yalnızca içini gösterdiği nesneyi de-randomize eder. Bir stack adresini leak etmek libc'yi açığa çıkarmaz; kullanmayı düşündüğün her bölgede bir pointer leak etmen (veya ona chain'lemen) gerekir.

Beklenen sonuç: base'ler kurtarıldığında, exploit chain'inin geri kalanı için mutlak adresler oluşturur ve ASLR/KASLR artık hiçbir katkı sağlamaz.

Mitigation

References