Kernel Address Space Layout Randomization¶
Kernel image'ının yükleme adresini (ve memory region base'lerini) boot başına bir kez randomize et ki saldırganlar kernel kodunun ve data'sının konumunu hardcode edemesin.
Mechanism¶
Neden çalışır
Klasik kernel exploit'leri control flow'u sabit bir kernel adresine yönlendirir
— bir ROP gadget'ına, commit_creds'e ya da bir set_memory_x page'ine. Bu
yalnızca saldırgan kernel text'in nerede yaşadığını biliyorsa çalışır; bu da
randomize edilmemiş bir kernel'de build-time bir sabittir (örn.
0xffffffff81000000).
KASLR (CONFIG_RANDOMIZE_BASE) bu varsayımı kırar: boot'ta kernel
decompressor'ı rastgele bir offset (yani slide) seçer ve kernel image'ını
base + slide'a relocate eder. Kurmaya çalıştığı invariant şudur: herhangi bir
kernel sembolünün adresi boot başına bir sırdır, yani tahmini ya da eski bir
adresle inşa edilmiş bir payload yanlış page'e düşer ve temiz bir privilege
escalation yerine başarısız olur (tipik olarak bir crash).
x86-64'te fiziksel ve virtual yerleşimler ayrı ayrı randomize edilir; kernel
virtual base'i, yaklaşık 9 bit text-randomization entropy'si veren bir pencereden
çekilir ve slide, kernel'in large-page mapping'inin 2 MB granularity'sinde
uygulanır. CONFIG_RANDOMIZE_MEMORY ek olarak direct (physmap) mapping, vmalloc
ve vmemmap bölgelerinin base'lerini randomize eder. Entropy RDRAND/RDTSC'den
(ya da fallback olarak i8254 timer'dan) toplanır veya EFI stub üzerinden boot
edilirken firmware tarafından EFI_RNG_PROTOCOL / /chosen/kaslr-seed
device-tree property'si aracılığıyla sağlanır.
Slide bir kez seçilip asla yeniden atılmadığı için KASLR ancak tek bir kernel adresinin gizliliği kadar güçlüdür — güvenilir herhangi bir leak onu tamamen çökertir.
Userspace ASLR'den farkı temel iki noktadadır: KASLR slide'ı her process için değil, boot başına bir kez seçilir (re-randomize edilmez) ve user mapping'leri değil kernel text/data ile physmap/vmalloc/vmemmap region'larını hedefler.
Walkthrough¶
1. KASLR'nin compile edildiğini ve aktif olduğunu doğrula.
$ grep CONFIG_RANDOMIZE_BASE /boot/config-$(uname -r)
CONFIG_RANDOMIZE_BASE=y
$ grep CONFIG_RANDOMIZE_MEMORY /boot/config-$(uname -r)
CONFIG_RANDOMIZE_MEMORY=y
2. Boot başına slide'ı gözlemle. Yetkilerle, kernel text'in runtime base'i reboot'lar arasında farklılaşır:
# boot A:
$ sudo grep ' _text$' /proc/kallsyms
ffffffff8a800000 T _text
# boot B (same kernel, rebooted):
$ sudo grep ' _text$' /proc/kallsyms
ffffffff9d200000 T _text
# slide = runtime _text - link-time base (CONFIG_PHYSICAL_START region)
3. Debugging için devre dışı bırak (yalnızca test makineleri). KASLR kernel command line'da toggle edilir:
# /etc/default/grub
GRUB_CMDLINE_LINUX="... nokaslr" # disable
# (default, or "kaslr") leaves it enabled
Tek bir leak onu yener; KASLR isolation değildir
KASLR çıtayı yükseltir ama bir kernel adresi elde eden bir exploit'i durdurmaz.
Tek bir info leak — kısıtlanmamışsa /proc/kallsyms, bir uninitialized-memory
disclosure'ı, dmesg ya da bir microarchitectural oracle — slide'ı verir ve tüm
image'ı derandomize eder. KASLR, kptr-restrict,
kallsyms-address-restriction ve
dmesg-restrict gibi leak bastıran mitigation'larla
eşleştirilmelidir.
Detection¶
Çalışan config'te CONFIG_RANDOMIZE_BASE=y, cmdline'da nokaslr'nin yokluğu
(cat /proc/cmdline) ve reboot'lar arasında değişen bir kernel _text base'i —
hepsi KASLR'nin çalıştığına işaret eder.
Mitigation¶
(Residual risk / bypass.) KASLR, herhangi bir adres disclosure'ına (proc-kallsyms-symbol-address-leak), re-randomization'ın ucuz olduğu yerde brute force'a (aslr-brute-force) ve translation yapılarını yoklayan side channel'lara (entrybleed-kpti-kaslr-bypass) yenilir. function-granular-kaslr gibi daha ince taneli varyantlar, tek bir text leak'in değerini azaltır.
References¶
- The Linux Kernel documentation / kernelconfig.io. CONFIG_RANDOMIZE_BASE — Randomize the address of the kernel image (KASLR). — https://www.kernelconfig.io/config_randomize_base
- LKDDB. CONFIG_RANDOMIZE_BASE. — https://cateee.net/lkddb/web-lkddb/RANDOMIZE_BASE.html