House of Prime¶
Allocator'ın
max_fast/ arena bookkeeping'ini corrupt et ki keyfi büyüklükteki freed chunk'lar fastbin'lere yanlış sort edilsin ve kontrollü bir write versin.
Mechanism¶
Suistimal edilen invariant
_int_free, bir freed chunk'ın bir fastbin'e ait olup olmadığına size'ını per-arena max_fast watermark'ına (sonraki glibc'de global_max_fast denir) karşı karşılaştırarak karar verir. Bir size için fastbin index'i, fastbin_index(sz) formundaki check edilmeyen aritmetik bir ifadeyle hesaplanır; allocator sz'nin zaten max_fast'a karşı range-check edilmiş olduğuna güvenir. House of Prime bu varsayımı iki yönden kırar: (1) max_fast'ı çok büyük bir değere yükseltir ki büyük chunk'lar fastbin olarak nitelensin ve (2) fastbin_index'i underflow eden / arena içindeki fastbinsY[] array'inin başından attacker'ın seçtiği bir offset'e inen crafted bir size sağlar. Fastbin singly-linked insert, freed chunk'ın address'ini fastbinsY[idx]'e başka bir validation olmadan yazdığı için, idx'i kontrol etmek bir free()'yi bir heap pointer'ının near-arbitrary write'ına çevirir. Orijinal Maleficarum formunda ikinci aşama sonra arena pointer'ını (arena_key / mp_-bitişik state) overwrite eder, böylece sonraki allocation'lar tamamen attacker-kontrollü fake bir arena'dan servis edilir.
Bu, "House of" ailesinin en eskisidir: Phantasmal Phantasmagoria tarafından The Malloc Maleficarum (2005)'te Solar Designer'ın orijinal unlink() technique'ine bir halef olarak yayımlandı ve glibc < 2.4'te bulunan pre-tcache, pre-hardening ptmalloc'u hedefler.
Walkthrough¶
Klasik iki-adımlı formülasyon:
-
max_fast'ı şişir. Bitişik bir chunk'ın size field'ına bir heap overflow (veya arena state'ine ulaşan herhangi bir write) kullanarakmax_fast'ı büyük bir değere set et. Bundan sonra, normal 0x40–0x80 fastbin tavanından çok daha büyük bir chunk'ı free etmek onu hâlâ unsorted bin yerine fastbin path'inden geçirir. -
Index'i kontrol etmek için kötücül bir size seç. Fastbin index'i chunk size'ından türetilir. Size'ı out-of-range / underflow'lu bir index üreten bir chunk'ı free ederek, freed chunk'ın address'i
&fastbinsY[0] + offset'e, yani gerçek fastbin array'inden önceki arena field'larına yazılır. Seçilen offset arena'nın kendi metadata'sına iner.
/* conceptual — pre-2.4 ptmalloc, NOT runnable on modern glibc */
/* step 1: heap-overflow a *neighbour* chunk's size field so the write
reaches arena state and inflates max_fast to a huge value. After this,
even large chunks still take the fastbin path on free(). */
neighbour->size = CRAFTED_MAXFAST; /* overflow reaches arena -> max_fast := huge */
/* step 2: give a *victim* chunk a size whose fastbin_index(size) underflows,
then free it. The singly-linked fastbin insert writes &victim to
&fastbinsY[0] + offset, i.e. into arena fields *before* the real array. */
victim->size = CRAFTED_INDEX; /* size chosen so fastbin_index(size) is OOB/underflows */
free(victim); /* writes &victim into arena at a controlled offset */
/* step 3: that controlled write clobbers the arena pointer/key ->
the next malloc() is served from a fake arena we own. */
- Arena'yı hijack et. Arena pointer'ı (veya key'i) overwrite edilmişken, bir sonraki
malloc()attacker-kontrollütop,last_remainderve bin pointer'larına danışır, böylece allocator attacker'ın seçtiği bir pointer döndürür — saklı bir return address'i, bir GOT entry'sini veya bir function pointer'ı ezmeye uygun bir write-what-where.
Büyük ölçüde tarihsel
House of Prime modern glibc'ye uygulanmaz. glibc 2.4+'tan beri _int_free chunksize(p) <= 2*SIZE_SZ ve "size too large" sanity check'leri yapar, max_fast global_max_fast olarak yeniden adlandırılıp hardened yapıldı ve fastbin insertion sonradan fd / size validation'ı kazandı (malloc(): invalid next size, double-free check vb.). Bu technique'i drop-in bir modern exploit olarak değil, sonraki global_max_fast corruption primitive'lerinin (örn. House of Corrosion) kavramsal bir atası olarak ele al.
Sonraki primitive'ler global_max_fast'ı neden tekrar ziyaret eder
Corrupt edilmiş bir global_max_fast'in büyük allocation'ları fastbin path'i (insertion'ı görece zayıf check edilir) için uygun hale getirdiği fikri modern araştırmada hayatta kalır. House of Corrosion örneğin bir unsorted-bin attack'i global_max_fast'a yönlendirir ve sonra büyük chunk'ların fastbin free'lerini bir relative write primitive olarak kullanır — House of Prime içgörüsünün doğrudan bir torunu.
Detection¶
global_max_fast'ten çok daha büyük bir chunk'ın fastbin code path'ine ulaşan birfree()'si anormaldir; heap-sanitizing allocator'lar ve ASAN/MALLOC_CHECK_corrupt edilen size'ı işaretler.- Main thread için arena pointer'larının
&main_arena'dan sapması güçlü bir tamper sinyalidir.
Mitigation¶
- glibc 2.4+
_int_freeve_int_malloc'ta size/index sanity check'leri. global_max_fastnormalde meşru path'ler üzerinden writable değildir; sonraki glibc fastbinfdve "invalid next size" check'leri ekler.- Modern tcache front-end'i çoğu küçük free'yi fastbin path'ine ulaşılmadan önce yakalar.