House of Mind¶
Bir chunk'ın
NON_MAIN_ARENAbit'ini corrupt et kifree()heap_for_ptr()alignment matematiği üzerinden fake bir arena çözsün ve attacker'ın allocator write'larını seçtiği belleğe yönlendirmesine izin versin.
Mechanism¶
Suistimal edilen invariant: arena kimliği chunk address + bir size flag'inden türetilir, authenticate edilmez
ptmalloc bir chunk'a hangi arena'nın sahip olduğuna tamamen, güvenilir bir
list'e karşı hiç validate etmediği metadata'dan karar verir. NON_MAIN_ARENA
flag'i (bir chunk'ın size field'ının üçüncü bit'i) global main_arena ile
chunk address'ini bir HEAP_MAX_SIZE sınırına maskeleyerek bulunan heap-local
bir arena pointer'ı arasında seçim yapar:
#define heap_for_ptr(ptr) \
((heap_info *) ((unsigned long) (ptr) & ~(HEAP_MAX_SIZE - 1)))
#define arena_for_chunk(ptr) \
(chunk_non_main_arena (ptr) ? heap_for_ptr (ptr)->ar_ptr : &main_arena)
Eğer attacker bir chunk'ta NON_MAIN_ARENA set ederse ve onun altındaki
HEAP_MAX_SIZE-hizalı address'teki belleği kontrol ederse, o zaman
heap_for_ptr(ptr)->ar_ptr attacker'ın seçtiği bir arena pointer'ı okur.
free() sonra tamamen forge edilmiş bir malloc_state üzerinde çalışır. Arena
seçimi gerçek arena registry'sine karşı check edilmeyip hesaplandığı için,
tüm free path yeniden yönlendirilebilir.
Walkthrough¶
Köken: Phantasmal Phantasmagoria, The Malloc Maleficarum (2005). Orijinal GOT-overwrite formu patch'lendi (unsorted-bin validation, ~glibc 2.11). Fastbin varyantı (Maxwell Dulin tarafından canlandırıldı) sürümler boyunca bir write-where primitive olarak hayatta kalır ve bugün pratik formdur.
Fastbin varyantı bir WRITE-WHERE verir: fastbin-boyutlu bir chunk'ın free()'si o
chunk'ın address'ini fake_arena->fastbinsY[idx]'e yazar. Attacker yazılan
konumu kontrol eder (fake arena'yı yerleştirerek), ama değer freed chunk'ın
address'idir (farklı heap offset'lerinde chunk'lar free ederek ayarlanabilir).
-
Alignment için heap feng shui. Allocation'ları spray et ki kontrol edilebilir bir bölge
HEAP_MAX_SIZE-hizalı bir address'te otursun (writeupHEAP_MAX_SIZE'ı ampirik olarak ölçtü ve 64-bit Ubuntu'da alignment'ı tutturmak için ~0x2000000–0x4000000churn olduğunu not eder).heap_for_ptr()victim chunk'ı bu base'e maskeleyecek. -
heap_info+ fake arena forge et. Hizalı base'de,ar_ptr'si senin fakemalloc_state'ine işaret eden birheap_infoyaz. Fake arena'da şunları set et: fastbinsYarray'ini doğru struct offset'inde (2.23'te 0x8; 2.27+'da 0x10, çünkühave_fastchunkseklendi) ve-
next-size sanity check'ini geçecek kadar büyük
system_mem(2.23'te ~0x880 / 2.29'da ~0x888 offset). -
Write'ı nişanla. Hedef
fake_arena + fastbinsY_offset + (fastbin_index * 8)'dir. Belirli bir chunk size'ıyla bir target addressT'ye write indirmek için, fake arena base'ini bu offset'ler tekrarT'ye toplanacak şekilde set et (örn. 2.23, 0x30 chunk, target0x5555554444→ arena0x5555554444 - 8 - 8'de).
!!! warning "Footgun: overflow yapılan chunk main arena'da yaşamalı"
Non-main arena'lar bir size cap dayatır, dolayısıyla corrupt edilen fastbin
chunk'ın kendisi main_arena'ya ait olmalı; sadece onun forge edilmiş
NON_MAIN_ARENA bit'i resolution'ı yeniden yönlendirir. glibc 2.26+'da
ilgili tcache bin'i dolu olmalı ki chunk tcache yerine fastbin path'ini alsın.
-
Chunk'ı corrupt et. Target chunk'ın size field'ında
NON_MAIN_ARENAbit'ini set et (tek-byte'lık bir overflow yeter). Sonraki chunk'ın size'ı fastbin sanity check'ini geçmek için0x10 <= size < arena->system_mem'i sağlamalı — fake arena'dasystem_mem'in büyük forge edilmesinin nedeni budur. -
Write'ı tetikle. Corrupt edilen chunk'ı
free()et.arena_for_chunk()fake arena'ya yönlendirir;_int_freechunk pointer'ınıfake_arena->fastbinsY[idx]'e insert eder, yani seçtiğin target'a bir heap pointer yazar.
??? example "Primitive özeti"
controlled: WHERE (address = fake_arena + fastbin offset)
value: freed chunk address (tune by freeing different chunks)
=> overwrite a function pointer / adjacent metadata with a heap pointer
Detection¶
NON_MAIN_ARENAbit'i set olan ama hizalıheap_info'su gerçek bir registered arena'ya karşılık gelmeyen bir freed chunk tutarsızdır.- Allocator'ın
fastbinsYsandığı ama bilinen herhangi bir arena'nın dışında olan belleğe yapılan write'lar allocator instrumentation'ı tarafından yakalanabilir.
Mitigation¶
- Orijinal unsorted-bin formu glibc ~2.11 validation'ı tarafından öldürüldü.
- Fastbin size sanity'si (
<= 0x10/>= system_mem) fastbin varyantını kısıtlar ama büyük birsystem_mem'li fake arena sağlandığında durdurmaz. - tcache (2.26+) küçük boyutlar için araya girer, dolayısıyla attacker fastbin path'ine ulaşmak için önce eşleşen tcache bin'ini tüketmeli.