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.