jemalloc exploitation¶
jemalloc'ta inline free-list pointer'ları ya da dlmalloc tarzı unlinking yoktur, dolayısıyla exploitation run/chunk metadata'sını corrupt etmeye ya da same-size region'ları groom ederek
malloc()'a hâlâ kullanımda olan memory'ye bir pointer döndürtmeye odaklanır.
Mechanism¶
Invariant: jemalloc out-of-band run/chunk bookkeeping'inin gerçekte canlı olanla tutarlı olduğuna güvenir
dlmalloc/ptmalloc'un aksine, jemalloc neredeyse hiç allocator metadata'sını user data'nın
yanında inline saklamaz ve (argp & huku'ya göre) "dlmalloc'un exploitation'ı için catalytic
olduğu kanıtlanmış 'unlinking' ya da 'frontlinking' gibi kavramları implemente etmez."
Bunun yerine bookkeeping'i ayrı yapılarda tutar ve onlara güvenir. Exploitation amacı
dolayısıyla bir linked-list operasyonunu hijack etmekten malloc()'u zaten canlı bir
region'a pointer döndürmeye zorlamaya (region duplication / overlap) kayar; bu ya o
out-of-band metadata'yı corrupt ederek ya da aynı size-class'taki free list'leri groom
ederek başarılır. Aynı size class'taki region'lar bir run içinde araya giren metadata
olmadan contiguous şekilde paketlendiği için, linear bir overflow allocator header'ları
yerine doğrudan sonraki region'ın user data'sını corrupt eder — yani victim bir chunk
header değil, komşu bir objedir.
Walkthrough¶
jemalloc'un allocation hiyerarşisi, Pseudomonarchia jemallocum (Phrack 68)'de tarif edildiği gibi:
arena (arena_t) highest abstraction; per-thread to reduce lock contention,
| owns the chunks and bins below it
+-- chunk (arena_chunk_t) large mmap'd region (1-4 MB); keeps a back-pointer to its arena
| +-- run (arena_run_t) contiguous pages serving ONE size class;
| | carries a bitmask of region alloc state
| | +-- region the actual malloc() return value
+-- bin (arena_bin_t) tracks the free regions / runs for a size class
Makaledeki size class'lar: small/medium region'lar bir page'den küçüktür; large region'lar small/medium'dan büyük ama huge'dan (chunk size eksi header'lar) küçüktür.
Primitive 1 — adjacent same-size region overflow. Aynı size-class'taki region'lar aralarında metadata olmadan bir run'ı paylaşır, dolayısıyla bir heap overflow sonraki region'ın içeriğini corrupt eder. jemalloc exploitation'ının yoğun şekilde heap grooming / feng shui'ye yaslanmasının nedeni budur: overflow eden region'ın hemen ardındaki region'a bir target obje (örn. vtable pointer'ı olan bir C++ objesi ya da bir length field) yerleştirirsin.
Primitive 2 — run-header metadata corruption. Bir run, region'larından hangilerinin free
olduğunu bir bitmask ile takip eder. Makale, ilk free element'i kaydeden run-header field'ının
overwrite edilmesini tarif eder ki malloc() zaten allocate edilmiş bir region'a pointer
döndürmeye yönlendirilir; bu da overlapping memory'ye iki canlı pointer üretir (region
duplication).
Tam run/region field adları versiyona özgüdür
jemalloc'un internal struct layout'u (ve run'ın free-element index'i, regions bitmask'i ve
arena_chunk_t arena pointer'ı gibi field adları) Firefox'un mozjemalloc'u, stand-alone
jemalloc ve sonraki Android/FreeBSD versiyonları arasında esaslı şekilde değişti. Herhangi
bir spesifik corruption'a güvenmeden önce field offset'lerini tam target build'e karşı
unmask_jemalloc gibi bir tool ile doğrula — offset'leri 2012 write-up'larından kopyalama.
Primitive 3 — chunk-header corruption. Her region, adresini chunk sınırına kadar maskeleyerek
kendisine ait arena_chunk_t'yi bulabilir. Chunk header'ı corrupt etmek — özellikle sakladığı
arena pointer'ını — o chunk'taki bir region'ın sonraki bir free()'sinin attacker-influenced
data'yı dereference etmesi demektir.
Primitive 4 — thread-cache (magazine) targeting. Preallocate edilmiş region'ların per-thread cache'leri de normal path üzerinden allocate edilir, dolayısıyla sıradan region'lar arasında yaşarlar ve gelecek allocation'ların hangi pointer'ları döndüreceğini etkilemek için diğer herhangi bir obje gibi corrupt edilebilirler.
Canlı jemalloc state'ini unmask_jemalloc ile incelemek
argp'nin unmask_jemalloc'u (Black Hat USA 2012 talk'uyla yayımlandı) canlı
arena'ları/chunk'ları/run'ları gezen bir debugger plugin'idir; böylece size class'ları ve
region layout'unu tahmin etmek yerine gerçek target üzerinde doğrulayabilirsin:
Detection¶
- Komşu region'lara overflow'ları ve duplicate edilmiş region'ların use-after-free'sini
yakalamak için target'ları AddressSanitizer / debug
MALLOC_OPTIONS/junkfill altında çalıştır. - İki ayrı allocation'ın overlapping adreslere çözülmesini (region duplication) gözle.
Mitigation¶
- Allocator metadata'sını ve guard logic'ini güncel tut; modern jemalloc debug build'lerde redzone/junk-filling ekler ve burada incelenen 2012 dönemi koduna göre daha fazla bookkeeping doğrular.
- Grooming'i zorlaştırmak için untrusted, attacker-sized objeleri dedicated arena'lara/size class'lara izole et.
- Tasarımın açığa çıkardığı adjacent-region overflow'larını tespit etmek için compile-time/ASan instrumentation.
References¶
- Pseudomonarchia jemallocum (argp & huku), Phrack 68:0x0a — Phrack Magazine
- argp — research index (jemalloc talk + unmask_jemalloc) — Patroklos Argyroudis
- unmask_jemalloc: De Mysteriis Dom jemalloc — argp (tooling)