Exploiting VLC — chaining two demuxer heap overflows against jemalloc¶
Phrack 68 case study'si (argp & huku, "Exploiting VLC: A case study on jemalloc heap overflows"): VLC'nin iki demuxer'ındaki heap overflow'ları jemalloc'a karşı silah haline getirir; komşu region'ları groom'layarak çalışır, çünkü jemalloc metadata'yı out-of-line tutar ve inline-header smashing yerine layout kontrolünü ödüllendirir. (Başlıktaki "iki", karşılaştırılan iki jemalloc implementasyonuna değil, zincirlenen iki demuxer overflow'una atıfta bulunur.)
Mechanism¶
Note
jemalloc allocation'ları per-thread arena'lara ayırır; her arena PAGE_SIZE hizalı run'lara bölünür; bir run tek bir size-class bin'ine hizmet eder ve tek tek allocation'lar bir run'dan kesilen region'lardır. Önemli nokta: jemalloc "region'ların kendi içine gömülü meta-information'ı kullanmaz" — chunk/run metadata'sı out-of-line tutulur. Yani glibc'nin aksine buffer'ının yanındaki bir inline header'ı smash'leyemezsin; exploitation bunun yerine komşu region layout'unu kontrol etmeye dayanır, böylece bir overflow seçilen tipte komşu bir object'i corrupt eder. Magazine cache açıkken region'lar azalan adreslerde dağıtılır; bu da attacker'ın ayarlaması gereken overflow yönünü belirler. Bu azalan-adres davranışı FreeBSD jemalloc'a (Phrack 68'in analiz ettiği 8.2-RELEASE) ve magazine katmanına özgüdür; modern jemalloc / standalone build'lerde farklılık gösterebilir, hedef build'de doğrulanmalıdır.
Walkthrough¶
VLC case study'si iki demuxer overflow'unu tek bir exploit chain'inde birleştirir (Phrack 68). İki bug bağımsız case study değil, birbirini tamamlar: Real Media Sipr overflow'u bir memory-disclosure (info-leak) primitive'i sağlar, MP4 demuxer overflow'u ise pointer manipulation üzerinden kontrol akışını hedefler. Leak, MP4 exploitation'ının heap layout'unu tahmin ederek güvenilir hale gelmesini sağlar:
/* MP4_ReadBox_skcr(): allocates a 4-byte MP4_Box_data_frma_t
but writes 12 bytes -> 8-byte heap overflow into the next region */
/* DemuxAudioSipr() (Real Media demuxer): overflow triggered when
i_subpacket_h == 0, overrunning the audio block buffer */
Grooming ve corruption yolu:
- Size class'ları profille: overflow'lanan object ile aynı bin'e düşen
allocation'ları (
block_taudio buffer'ları,MP4_Box_tnode'ları) seç ki run komşusu olsunlar. - Bir run'ı doldurmak için spray yap, sonra bir hole free'le ve reallocate et ki victim object overflow kaynağının hemen ardına (ya da magazine'ler altında öncesine) otursun.
- Demuxer overflow'unu tetikleyerek komşu
block_t(p_buffer/i_buffer) veyaMP4_Box_tfield'larını corrupt et; overflow'u kontrollü bir pointer/length'e ve nihayetinde bir write primitive'ine dönüştür.
Warning
Güvenilirlik deterministik run/region yerleşimine bağlıdır; jemalloc'un per-thread arena'ları ve magazine caching'i, grooming'in thread affinity'sini ve azalan-adres allocation sırasını hesaba katmasını gerektirir. Offset'ler application'a ve jemalloc versiyonuna özgüdür.
Detection¶
- Demuxer buffer'ları çevresinde heap canary'leri / guarded allocator'lar; media parser'larda ASan.
- jemalloc'un
redzone/junkdebugging seçenekleri overrun'ı ortaya çıkarır.
Mitigation¶
- Modern jemalloc redzone'ları, guard page'leri ve pointer-bound check'leri; bounds-checked media parsing; demuxer'ları fuzz'larken ASan/MSan.