Skip to content

Constant-Embedded Gadget JIT Spray (partial-blinding bypass)

Saldırgan byte'larını büyük immediate constant'lar olarak executable bir JIT page'ine kaçır, sonra instruction'ın ortasından (unaligned) gir ki bunlar NOP-sled-artı-gadget olarak yeniden decode olsun — partial constant blinding'i yenmek.

Mechanism

Note

Bir JIT, saldırgan script'inden gelen herhangi bir literal constant'ı doğrudan executable page'e bir instruction immediate'i olarak emit eder. x86 instruction'ları değişken uzunlukta ve unaligned olduğundan, saldırgan büyük constant'lardan oluşan bir XOR-chain'in binlerce kopyasını spray'ler, sonra kontrolü amaçlanan sınırdan bir byte kaymış hâlde transfer eder. O unaligned offset'te constant byte'ları tamamen farklı, saldırgan tarafından seçilmiş bir instruction stream'i olarak yeniden decode olur — baştaki byte'lar bir NOP sled gibi davranır (böylece imprecise bir jump yine de iner) ve sonraki byte'lar gadget/shellcode'u oluşturur. Bu, W^X'i (JIT page executable'dır) ve ASLR'yi (spray'in yüksek isabet olasılığı) bypass eder.

Standart savunma constant blinding'dir: emit edilen her immediate'i rastgele bir cookie ile XOR et (emit(K ^ cookie); xor reg, cookie) — bu, baseline JIT spray'e karşı standart bir savunmadır. Bu atom, blinding yapmayan ya da yalnızca bazı constant'ları blind eden (örn. small immediate'leri veya FP double mantissa'larını blind edilmemiş bırakan) JIT'leri suistimal eder.

Walkthrough

Bir XOR-chain için aligned JIT çıktısı (dört immediate byte saldırgan tarafından kontrol edilir):

0:  b8 44 33 22 11      mov  $0x11223344,%eax
5:  35 11 22 33 44      xor  $0x44332211,%eax
a:  35 11 22 33 44      xor  $0x44332211,%eax

Offset 1'e (immediate'in içine) jump etmek, aynı byte'ları şöyle yeniden decode eder:

1:  44                  inc  %esp
2:  33 22               xor  (%edx),%esp
4:  11 35 11 22 33 44   adc  %esi,0x44332211
a:  35 11 22 33 44      xor  $0x44332211,%eax

Blazakis'in klasik ActionScript demosu 0x3c909090 constant'ını zincirledi: off-by-one offset'te 90 90 90 byte'ları nop; nop; nop (bir sled) olarak decode olur ve 3c bir sonraki opcode'u başlatır, böylece her 4-byte immediate üç NOP artı bir gadget byte verir; güvenilir bir sled+payload kurmak için tekrarlanır.

Dachshund: defeating partial blinding (NDSS 2015)

Athanasakis et al., gerçek engine'lerin yalnızca ≥3-byte immediate'leri blind ettiğini, typed array'lerdeki 1-/2-byte constant'ları ve floating-point/double mantissa'larını blind edilmemiş bıraktığını gösterdi. Gadget'ı hayatta kalan bu constant'lara paketlemek hâlâ dinamik ROP-gadget injection'ına izin verir (Firefox ve 64-bit IE'de gösterildi). Blinding'i küçük constant'lara genişletmek ~%80'e varan maliyet getiriyordu, bu yüzden engine'ler yapmadı.

Detection

Birbirine neredeyse özdeş çok sayıda JIT allocation'ı (spray imzası), constant açısından yoğun hot fonksiyonları ve JIT page'leri içinde non-instruction sınırlarına inen control transfer'leri için izle.

Mitigation

Tüm immediate'leri blind et (küçük + FP dahil), JIT page'leri için W^X dayat (çift RW/RX mapping, asla RWX), constant pooling (literal'leri non-executable bir data pool'una taşı), rastgele NOP ekleme ve unaligned girişi yasaklamak için JIT-page girişinde CFI. Bkz. JIT spray ve LeJIT.

References