Skip to content

House of Rabbit

Fastbin chunk'larını size'larını yeniden validate etmeden merge eden malloc_consolidate()'i suistimal ederek fake bir free chunk forge et — size field'ı en büyük largebin'e inmek için adres uzayını wrap eden bir varyant dahil.

Mechanism

Suistimal edilen invariant

Fastbin allocator'ı bir chunk'ın size'ını fastbin'e insert edildiğinde / fastbin'den remove edildiğinde validate eder (malloc(): memory corruption (fast) tarzı check'ler). Ama malloc_consolidate() — büyük bir request servis edilemediğinde veya top chunk büyütüldüğünde invoke edilir — fastbin list'lerini dolaşır ve her chunk'ı size'ı global_max_fast'a karşı yeniden check etmeden unsorted bin'e taşır ve fd link'lerini körü körüne takip eder. House of Rabbit bir fastbin entry'sine forge edilmiş bir size (veya attacker-kontrollü belleğe işaret eden forge edilmiş bir fd) enjekte eder, sonra consolidation'ı tetikler. Allocator forgery'yi meşru bir free chunk gibi muamele eder ve overlapping chunk'lar veya ileri formda bir largebin'e sort edilen bir chunk üretir. Consolidation size aritmetiğine güvendiği için, virtual address space'i wrap edecek şekilde craft edilmiş bir size field, en büyük largebin (bin[126]largebin_index bu index'te satüre olur; standart glibc'de bin[127] array'de var olsa da index fonksiyonu 126'dan büyük değer döndürmez, dolayısıyla size ile ulaşılabilen en büyük largebin bin[126]'dır) için largebin range check'ini sağlayacak hale getirilebilir, böylece fake chunk oraya fd_nextsize / bk_nextsize üzerinden link'lenir.

glibc'nin ~2.28 consolidation/size hardening'inden önceki sürümlerine uygulanır; 2017–2018 civarında public olarak gösterildi (örn. HITB-XCTF 2018 "mutepig"). Orijinal PoC shift-crops tarafından.

Walkthrough

İki standart formülasyon var.

Variant A — size değişikliğiyle overlap

/* glibc 2.23-ish, conceptual */
a = malloc(0x30); b = malloc(0x30);   /* fastbin-sized */
free(a); free(b);                     /* both in 0x40 fastbin */

/* UAF/overflow: enlarge a's size so it spans b too */
*(size_t*)((char*)a - 8) = 0xa1;      /* 0x41 -> 0xa1 */

malloc(0x1000);                       /* forces malloc_consolidate() */
/* a is moved to unsorted bin at size 0xa0 WITHOUT a size recheck,
   creating a chunk that overlaps b => overlapping-chunks primitive */

Konsolide edilen a artık sonraki allocation'larla overlap eder ve bir arbitrary-overlap / type-confusion write verir.

Variant B — fake largebin chunk (size wrap)

  1. Attacker-kontrollü belleğe, consolidation'dan sonra unsorted-bin sort loop'unun onu en büyük largebin'e (bin[126]) sınıflandıracağı şekilde seçilmiş bir size ile forge edilmiş bir chunk yerleştir. Bu, largebin index'inin satüre olacağı kadar büyük bir size gerektirir; onu oluşturmak tipik olarak iki overlapping size field'ı (biri fake chunk için, biri ondan 0x10 önce konumlanmış bir successor chunk için) ve size aritmetiğinde wrap eden bir değer kullanır.
  2. malloc_consolidate()'i tetikle (large request), böylece fastbin'de bulunan forge edilmiş chunk unsorted bin'e taşınır.
  3. Largebin'lerdeki herhangi bir şeyden daha büyük bir chunk iste ki unsorted-bin loop'u fake chunk'ı bin[126]'ya sort etsin ve fd_nextsize / bk_nextsize'ı bağlasın.
  4. Fake largebin chunk'ı artık bir large-bin attack için veya attacker'ın seçtiği bir address'te gelecekteki bir allocation'ı karşılamak için bir staging primitive'idir.

Footgun: consolidation invariant'ları

Consolidation sonraki chunk'ın prev_inuse / prev_size'ına da dokunur. Tutarlı bir takip eden chunk sunmayan yanlış-craft edilmiş bir forge chunk unlink/consolidation'ı crash eder. Fake chunk ve successor'ının size field'ları karşılıklı tutarlı olmalı, largebin varyantının iki overlapping size word'ü yerleştirmesinin nedeni budur.

Bu düz bir fastbin attack'i neden geçer

Normal bir fastbin attack target'ta gerçek, size-hizalı fake bir chunk ister. House of Rabbit sadece zaten freed bir fastbin chunk'ının bir size'ının veya fd'sinin kontrolünü ister; gerisini consolidation yapar ve size'ı asla check etmez, dolayısıyla target'ta doğal bir size alignment olmasa bile "bir overlap chunk oluşturmak kolaydır".

Detection

  • Fastbin aralığı dışında bir size ile consolidation üzerinden bir fastbin'den ayrılan bir chunk anormaldir.
  • Heap arena'sının dışına işaret eden largebin fd_nextsize/bk_nextsize forge edilmiş bir largebin chunk'ını gösterir.

Mitigation

  • glibc ≥ 2.28 consolidation / _int_free size check'lerini sıkılaştırdı.
  • Sonraki glibc, birçok forge edilmiş successor chunk'ı yakalayan malloc(): invalid next size ve unsorted-bin integrity check'leri ekler.
  • tcache (2.26+) küçük free'leri fastbin/consolidation path'ine ulaşmadan önce yakalar ve doğal fırsatı azaltır.

References