Structures-Before-Canary Overwrite¶
Exploit hedefine, memory'de stack canary'den önce duran local variable'lara, struct'lara ya da saved pointer'lara overflow ederek ulaş — cookie'nin kendisine asla dokunmadan ya da onu leak etmeden.
Mechanism¶
Neden işe yarar
Bir stack canary (__stack_chk_guard) yalnızca saved return address'i ve
saved frame pointer'ı korur: compiler cookie'yi local buffer'lar ile saved
RIP arasına yerleştirir ve __stack_chk_fail yalnızca cookie function
epilogue'unda değişirse abort eder. Compiler'ın canary'nin altına (daha
düşük adreslere, bir forward overflow'un önce yazdığı yere) yerleştirdiği
local variable'lar, in-frame structure'lar ve pointer'lar hakkında hiçbir şey
söylemez. Exploitation hedefine o komşu object'lerden birini bozarak
ulaşılabilirse — bir offset/index variable'ı, bir function pointer, bir
FILE*, bir length field'i, bir loop counter'ı — canary asla overwrite
edilmez, __stack_chk_fail asla ateşlenmez ve function normal şekilde return eder.
Bir canary'nin zorunlu kıldığı invariant "saved return address linear olarak overwrite edilmedi"dir. Canary'den önce kalan bir overflow, programı yine de hijack ederken o invariant'ı sağlam bırakır, dolayısıyla savunma basitçe saldırının data path'inde değildir.
Walkthrough¶
Klasik target: overflow'a uğramış buffer'a komşu yerleştirilmiş bir index/offset variable'ı. Onu overflow etmek bir sonraki write'ın nereye ineceğini değiştirir ve saldırganın canary slot'unu atlarken return address'e doğrudan ulaşmasını sağlar.
char buf[16];
int i; /* lives next to buf; controls the write offset */
for (i = 0; ; i++) {
buf[i] = getchar();
if (buf[i] == '\n') break;
}
"While overflowing
bufwith your 17th character, it will end up overflowing into the localivariable. This variable will decide in the next iteration at what offset the rest of the data will be written" — bu da saldırganın canary'yi tamamen atlayıp doğrudan return address'e yazmasını sağlar.
Cookie'yi yenen diğer komşu object'ler
scanf("%lf")atlaması: tek başına bir.beslemek target variable'ı overwrite etmeden bırakır, böylece bir write dizisi canary'nin üzerinden adımlayıp cookie'yi bozmadan return pointer'a inebilir.- Komşu function pointer /
longjmpbuffer'ı / SEH record'u: canary'nin altında saklanan callable bir pointer'ı overwrite etmek, epilogue check'i hiç çalışmadan, bir sonraki indirect call'da control flow'u yönlendirir. - Sonraki bir copy'nin length / size field'i: sonraki bir
memcpy'yi sınırlayan bir in-frame struct member'ını bozmak, küçük bir overflow'u, kendisi yalnızca return address'i hedefleyen bir arbitrary write'a çevirir.
Layout garanti değildir
Yararlı bir object'in gerçekten canary'den önce durup durmadığı; compiler version'ına, optimization level'ına ve reordering'e bağlıdır. Bazı GCC/Clang version'ları, bu maruziyeti azaltmak için array'leri scalar'ların üstüne taşıyabilir (stack-protector'ın local-reordering davranışı; garanti değildir ve optimization level'ına bağlıdır — bkz. Stack Protector / SSP) ve randstruct kernel struct layout'unu randomize eder. Saldırı yalnızca exploitable bir object'in cookie'den önce ulaşılabilir olduğu durumda işler.
Mitigation¶
Bu sınıf canary'nin kendisi tarafından durdurulmaz. Onu durduran şey:
- Array'ler scalar'ların üstüne gelsin diye local'leri yeniden sırala
(stack-protector'ın local-reordering davranışı):
-fstack-protector-stronghangi function'ların instrument edileceğini seçer, layout kararları ise compiler version'ına ve optimization level'ına bağlıdır. İdeal durumda index/offset ve pointer variable'larını buffer'ın üstünde tutar, böylece bir forward overflow onlara ulaşmadan önce canary'ye tosar. - Bounds/overflow eliminasyonu — _FORTIFY_SOURCE ve Stack Variable Auto-Init, overflow primitive'ini kaldırır ya da kısıtlar.
- Pointer-seviyesi integrity — Intel CET shadow stack return address'i bağımsız olarak korur ve Code-Pointer Integrity, bir structures-before-canary write'ının aksi halde bozacağı in-frame code pointer'ları korur.
Leak/brute sınıflarıyla karşılaştır — Stack Canary Leak ve Byte-by-Byte Canary Brute Force — bunlar bunun yerine cookie değerini kurtararak aynı savunmayı yener.