Heap spray¶
Heap'i kontrol edilen data/object'lerin birçok kopyasıyla doldurarak bir corruption primitive'inin güvenilir biçimde attacker byte'larına denk gelmesini sağlamak.
Mechanism¶
Heap spraying tek başına bir bug exploit etmez — "bir target process'in belleğinde önceden belirlenmiş bir konuma belirli bir byte dizisi koymaya çalışır" ve layout'un öngörülemezliğini telafi etmek için "büyük miktarda düzen ekler" ki bir corruption primitive'i güvenilir biçimde attacker-controlled byte'lara insin.
Note
Tarihsel olarak (browser/userland) sprey'lenen byte'lar hem NOP sled hem de shellcode görevi görürdü.
Modern kernel exploitation, freed bir object'i reclaim etmek için slab allocator'ı sprey'ler: kmalloc()
sırasında allocator yakın zamanda free'lenmiş belleği döndürür, dolayısıyla kontrollü içerikle aynı boyutta bir
object allocate etmek, savunmasız freed object'in üzerine yazar.
Walkthrough¶
Userland/browser (tarihsel): sprey'ler "çoğunlukla JavaScript'te uygulanır ve büyük
string'ler oluşturarak heap'i sprey'lerdi", bir değeri tekrar tekrar concatenate ederek. x86'da
tekrarlanan 0x0c0c0c0c word'ü hem geçerli bir jump adresi hem de bir NOP eşdeğeri görevi görür, böylece
sprey içinde herhangi bir yere inmek shellcode'a akar.
Kernel/slab (modern UAF reclaim): allocator boyuta göre bucket'ladığından ("33 ile 64 byte
arasındaki herhangi bir allocation isteği … 64-byte bucket'tan karşılanır"),
attacker freed bir slot'u reclaim etmek için kontrollü data içeren birçok aynı boyutlu object sprey'ler — örn.
msgsnd(), setxattr veya sendmsg ancillary data üzerinden.
/* reclaim a just-freed kmalloc-64 object */
for (int i = 0; i < N; i++)
msgsnd(qid[i], &ctrl, CTRL_SZ, 0); /* ctrl payload overwrites the freed object */
Detection¶
KASAN, altta yatan UAF/OOB'yi raporlar; spraying'in kendisi sıradan allocation trafiğidir ve tek başına büyük ölçüde tespit edilemez. Slab-quarantine / KASAN delayed-free, spraying'in dayandığı zamanlamayı bozar.
Mitigation¶
Kernel slab quarantine (CONFIG_SLAB_QUARANTINE) freed allocation'ları tutar ki "anında
yeniden allocate edilemesinler", isteğe bağlı olarak reclaim edilen belleği sıfırlar. Randomize / per-call-site
kmalloc bucket'ları (kernel 6.6 her bucket'ı 16 yönde böler ve call site başına rastgele bir bucket seçer)
ve özel kmem_buckets_create(), user tarafından kontrol edilebilen allocation'ları ayırır.
Userland: ASLR/DEP, tarihsel NOP-sled'den-shellcode'a modelini yener.