Skip to content

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:

  1. Size class'ları profille: overflow'lanan object ile aynı bin'e düşen allocation'ları (block_t audio buffer'ları, MP4_Box_t node'ları) seç ki run komşusu olsunlar.
  2. 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.
  3. Demuxer overflow'unu tetikleyerek komşu block_t (p_buffer/i_buffer) veya MP4_Box_t field'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/junk debugging 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.

References