Skip to content

Blind Return-Oriented Programming (BROP)

Crash sonrası yeniden başlayan bir servisteki stack overflow'u uzaktan exploit et; crash-vs-hang'i bir oracle olarak kullanarak secret'ları leak'le ve ROP gadget'larını bul — binary olmadan.

Mechanism

Note

Bittau, Belay, Mashtizadeh, Mazières & Boneh'nin "Hacking Blind" (IEEE S&P 2014) çalışmasından. İki koşul blind exploitation'ı mümkün kılar: (a) bir stack-overflow bug'ı ve (b) bir crash sonrası worker'ları fork/restart eden, ASLR'yi ve stack canary'sini restart'lar boyunca değişmeden bırakan bir server (child, parent'ın layout'unu miras alır). Bu bir crash oracle verir: belirli bir byte'ın crash'e yol açıp açmadığı bir bit leak eder ve layout stabil olduğu için secret'lar her seferinde bir byte brute-force edilir — 2^64 değil, lineer.

Invariant şu: restart-stabil bir address space, "64-bit'lik bir secret'ı tahmin et"i "8 byte tahmin et, her biri için ~256 deneme"ye çevirir. Tam atak sonra gadget'ları, target binary'nin hiçbir kopyası olmadan, tamamen crash davranışından keşfeder.

Walkthrough

1. Stack reading — canary'yi, sonra kaydedilmiş return address'i byte byte leak'le:

known = b""
for pos in range(8):
    for guess in range(256):
        payload = b"A"*OVERFLOW + known + bytes([guess])
        if send(payload) == NO_CRASH:    # correct byte -> overflow check passes
            known += bytes([guess]); break
# 'known' is now the canary; continue past it to leak saved RBP / return addr

2. Stop gadget — crash etmek yerine temiz dönen / blok'layan bir adres bul; scanning sırasında "kullanışlı gadget"ı "crash"ten ayırt eden bir marker olarak kullanılır.

3. BROP gadget__libc_csu_init'in altı-register'lık epilogue'u: pop rbx; pop rbp; pop r12; pop r13; pop r14; pop r15; ret. Bu tek diziye belirli byte offset'lerinden girildiğinde kısalan alt-dizileri ortaya çıkar — bir offset pop rsi; pop r15; ret, biraz ileriki offset ise pop rdi; ret gibi davranır — böylece ilk iki argüman register'ının (rdi, rsi) kontrolü elde edilir. Bu karakteristik altı-pop imzası, gadget'ı rastgele pop zincirlerinden ayırt eden şeydir (aynı fonksiyonda ret2csu tarzı bir mov ...; call [r12+rbx*8] gadget'ı da bulunur).

4. PLT entry'lerini bul — PLT'yi tara; adayları kontrollü argümanlarla çağırıp oracle'ı gözlemleyerek write'ı (ve strcmp'i) tanımla.

5. Binary'yi dump et — BROP gadget + write@PLT'yi zincirleyerek programın kendi memory'sini attacker socket'ine yaz ve binary'yi yeniden inşa et; sonra geri kazanılan symbol'lerden normal bir execve/dup2 ROP shell'i kur.

Beklenen sonuç (paper): gerçek server'larda (nginx, MySQL) ~4,000 istekte, ~20 dakikanın altında bir shell — ASLR'yi, NX'i ve stack canary'lerini blind şekilde yenerek.

Mitigation

  • Her fork/exec'te re-randomize et (ASLR layout'unu miras alma) ki crash oracle stabil bir bilgi vermesin — bu temel savunmadır.
  • Crash fırtınalarını tespit et: saniyede yüzlerce kez crash eden bir worker, monitoring/IDS için güçlü bir BROP imzasıdır.
  • Tek başına stack canary'leri işe yaramaz (byte-byte leak'lenirler); CFI/shadow stack'ler ve crash-rate limiting ile eşleştir.

References