Stack spraying¶
Önce controlled bir "spray" syscall'ı çalıştırarak, bir victim syscall'ın daha sonra uninitialized okuyacağı tam kernel-stack offset'ine attacker'ın seçtiği byte'ları yerleştir — zararsız bir use-before-initialization bug'ını controlled bir değere ya da fake-object pointer'ına çevirerek.
Mechanism¶
Note
Kernel, syscall'lar arasında yeniden kullanılan ve varsayılan olarak girişte sıfırlanmayan küçük bir per-thread stack (tipik olarak 8–16 KiB) allocate eder. Bir syscall bir stack variable'ını initialize etmeden önce okuduğunda (use-before-initialization / UBI), o stack offset'inde önceki bir syscall'ın bıraktığı her ne ise onu okur. Targeted stack spraying, önce controlled bir spray syscall'ı çalıştırarak victim'in daha sonra uninitialized okuyacağı tam stack offset'ine attacker'ın seçtiği byte'ları yerleştirir. NDSS 2017 makalesi (Lu, Walter, Pfaff, Nürnberger, Lee, Backes) iki yöntemi formalize eder: deterministic stack spraying, belirli bir stack derinliğinde attacker-controlled veri bırakan syscall input'larını bulmak için tailored symbolic execution'ı guided fuzzing ile birleştirir; ve exhaustive memory spraying, büyük bir bitişik stack bölgesini örter. Birleşik yaklaşım "Linux kernel stack'inin %91'inden fazlasını güvenilir biçimde kontrol edebilir" — UBI bug'larını privilege escalation'a çevirmeye yetecek kadar.
Walkthrough¶
- Bilinen bir frame offset'inde bir stack değerinin UBI read'ine sahip bir victim syscall'ı belirle (örn. daha sonra bir copy/dispatch'te kullanılan uninitialized bir pointer ya da length).
- Call graph'i aynı ya da daha derin stack derinliğine ulaşan ve oraya attacker-controlled
byte'lar yazan bir spray syscall'ı seç. Kernel stack'ine büyük controlled buffer'lar
kopyalayan klasik primitive'ler arasında
struct iovecarray'lerini ve ancillary/control-message (msg_control) buffer'larını marshal eden syscall'lar bulunur — geneldesendmmsg/sendmsgvewritev/readvailesi. Makalenin katkısı, böyle bir spray input'unu elle seçmek yerine onu otomatik olarak keşfetmektir. - Spray syscall'ını victim syscall'dan hemen önce, araya mümkün olduğunca az işlem girecek şekilde çağır — stack volatil'dir ve araya giren herhangi bir çağrı planlanmış byte'ları ezebilir.
- Victim daha sonra planlanmış değeri initialize edilmiş gibi okur: controlled bir pointer/değer (bir kernel pointer'ının info leak'i ya da hedef offset'e planlanmış bir fake-object pointer'ı).
Warning
Teknik timing-hassastır: spray ile victim arasında tek bir derin function call, planlanmış bölgeyi overwrite edebilir, bu yüzden iki syscall arka arkaya verilir.
Mitigation¶
Compiler tarafından zorlanan auto-initialization bu sınıfı doğrudan yener:
CONFIG_INIT_STACK_ALL_ZERO / CONFIG_INIT_STACK_ALL_PATTERN
(GCC/Clang -ftrivial-auto-var-init=zero|pattern), artı structleak ve stackleak
(CONFIG_GCC_PLUGIN_STACKLEAK, syscall return'de stack'i poison'lar).