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 iç 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:
- 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. - 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.
- Base'i hesapla. O sembolün bilinen statik offset'ini leak edilen adresten çıkararak nesnenin randomize edilmiş load base'ini elde et.
- 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. - 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)
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¶
- Pointer açığa çıkışını kısıtla:
kptr-restrict,kallsyms-address-restrictionvehashed-kernel-pointers,/proc/kallsymsve dmesg gibi arayüzler üzerinden kernel-pointer leak'lerini engeller (%pK/%phashing). - Uninitialized/stale pointer'ların leak olmasını önle:
init-on-alloc,init-on-freevestructleak-structure-auto-init. - Disclosure primitive'inin kendisini ortadan kaldır (format-string/OOB-read bug'ını düzelt); ASLR tek başına bir arbitrary read'e karşı savunamaz. İlgili leak güdümlü teknikler:
format-string-canary-leak,stack-reading.