Skip to content

House of Gods

glibc < 2.27 için arena-hijack tekniği: main_arena.next'i ve arena bookkeeping'ini bozarak thread_arena'yı tamamen attacker-controlled sahte bir arena'ya yeniden yönelt; ~8 allocation içinde allocator davranışı üzerinde neredeyse tam kontrol kazandır.

Mechanism

Suistimal edilen invariant

ptmalloc, arena'ları main_arena'da köklenen circular singly-linked bir listede tutar, malloc_state.next üzerinden zincirlenmiş, arena_max ile sınırlanan global bir narenas counter'ı ile. Bir thread bir arena'ya ihtiyaç duyduğunda ve limite ulaşıldığında, reused_arena(), next listesini gezer ve mevcut bir arena'yı adopt eder, onu per-thread thread_arena sembolüne atar — seçtiği malloc_state'in gerçek bir arena olduğunu asla yeniden validate etmeden. House of Gods sahte bir malloc_state forge eder, onu next ring'ine splice eder ve sonra reuse mantığını sürer ki main thread sahte arena'yı adopt etsin.

Zor kısım main_arena'nın kendisini düzenlemektir. House of Gods bunu bir binmap attack ile çözer: bir unsorted-bin layout'u imal eder ki sahte bir chunk, main_arena içindeki binmap field'ını (offset version-dependent, ör. 64-bit glibc 2.24 build'inde ~0x850) overlap etsin ve bir unsorted chunk üzerindeki tek bir write-after-free arena struct'ının içine insin. Oradan main_arena.next'i (offset version-dependent, ör. ~0x868) sahte arena'ya patch'ler ve system_mem'i kurcalar ki forge edilmiş arena üzerindeki sonraki size sanity check'leri geçsin. Bunların hiçbiri arena-reuse anında yeniden check edilmediğinden, forge edilmiş arena canlı olan olur.

Walkthrough

glibc < 2.27'ye uygulanır (2.23–2.26 gösterildi). Ön koşullar: bir heap leak, bir libc leak, bir chunk'ın user data'sının ilk ~5 quadword'ünün kontrolü ve bir unsorted chunk üzerinde tek bir write-after-free. Yayımlanmış exploit, arena'yı 8 allocation'da hijack eder ve 10'dan sonra bir shell düşürür.

  1. Layout. Heap'i kurmak için bir small chunk artı birkaç fastbin-boyutlu chunk allocate et. Fast chunk'lar daha sonra binmap chunk'ı için forge edilmiş size/bk field'ları sağlayacak.

  2. Unsorted bin'i hazırla. Small chunk'ı unsorted bin'e free et, sonra bir ara allocation yap ki allocator onu binning'e başlasın.

  3. Binmap attack (WAF). Unsorted chunk üzerindeki tek write-after-free'yi kullanarak unsorted-bin link'ini, main_arena'nın binmap bölgesini overlap eden sahte bir chunk'a yönlendir. Daha önce hazırlanan fast chunk'ları kullanarak o chunk için geçerli size field'ları ve bk pointer'ları forge et.

  4. Binmap chunk'ını allocate et. Bir request'i karşılamak binmap-chunk'ı, yani main_arena içinde bir pointer döndürür. Onun üzerinden yazmak artık arena field'larını doğrudan düzenler.

  5. narenas üzerinde unsorted-bin attack. Klasik bir unsorted-bin attack çalıştır ki sahte bck->fd = bin write'ı narenas counter'ına insin ve onu arena_max'in ötesine itsin ki allocator arena limitinin tükendiğine inansın ve bir tane oluşturmak yerine bir arena'yı reuse etsin.

  6. Sahte arena'yı kur. main_arena.next'i tamamen attacker-controlled sahte bir malloc_state'in adresine ayarla ve system_mem'i düzelt ki forge edilmiş arena size check'lerinden sağ çıksın.

  7. Adoption'ı zorla. İki reused_arena() çağrısı tetikle (örn. oversized allocation request'leri üzerinden). thread_arena artık sahte arena'ya yeniden atanır.

  8. Profit. Canlı arena kontrol altındayken, sahte malloc_state'teki fastbin/top-chunk pointer'ları bir arbitrary-allocation primitive'i verir; iki allocation daha bunu kontrollü bir write'a ve bir shell'e çevirir.

Footgun'lar

  • Binmap chunk'ının forge edilmiş size'ı geçerli bir binmap index'i üretmeli, yoksa sort mantığı abort eder; adım 1'deki fast-chunk hazırlığı tam olarak o kısıtlamaları sağlamak için vardır.
  • Bu pre-tcache bir tekniktir. glibc 2.27'den itibaren tcache, attack'ın dayandığı allocation yollarını short-circuit eder ve reused_arena() davranışı farklıdır, dolayısıyla House of Gods modern libc'ye doğrudan transplant edilmez.

Detection

  • libc'nin main_arena bölgesine değil de heap'e işaret eden bir thread_arena (ya da canlı arena pointer'ı) tanımlayıcı anomalidir.
  • arena_max'i aşan narenas ya da libc arena pool'unu terk eden bir main_arena.next link'i, güçlü integrity-checker sinyalleridir.

Mitigation

  • glibc ≥ 2.27 (tcache) chain'i yapısal olarak kırar; sonraki unsorted-bin hardening'i (bck->fd != victim check'i, 2.28) narenas write'ını kaldırır.
  • Reuse edilen bir malloc_state'in gerçekten bilinen arena belleğinde bulunduğunu validate etmek adoption adımını kapatır.

References