Skip to content

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:

  1. max_fast'ı şişir. Bitişik bir chunk'ın size field'ına bir heap overflow (veya arena state'ine ulaşan herhangi bir write) kullanarak max_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.

  2. 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. */
  1. Arena'yı hijack et. Arena pointer'ı (veya key'i) overwrite edilmişken, bir sonraki malloc() attacker-kontrollü top, last_remainder ve 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 bir free()'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_free ve _int_malloc'ta size/index sanity check'leri.
  • global_max_fast normalde meşru path'ler üzerinden writable değildir; sonraki glibc fastbin fd ve "invalid next size" check'leri ekler.
  • Modern tcache front-end'i çoğu küçük free'yi fastbin path'ine ulaşılmadan önce yakalar.

References