Skip to content

String-Oriented Programming

Bir format-string vulnerability'sini yalnızca tek bir read/write için değil, bir code-reuse dispatcher enjekte eden ve mevcut gadget'ları zincirleyen otomatik bir motor olarak kullanmak — ASLR, DEP ve canary'lerin hepsi etkinken bile.

Mechanism

Invariant

Bir format-string bug'ı (güvenilmeyen verinin bir printf-ailesi format argümanına ulaşması) attacker'a genel bir memory-read ve memory-write primitive'i verir: %n/%hn write yapar, positional specifier'lar (%7$p) keyfi stack/pointer-zincirli belleği okur (bkz. format-string-bug). Her savunma aynı bug üzerinden okunur veya yazılır: canary'ler kontrol edilmeden önce leak'lenir, ASLR canlı pointer'lar leak'lenerek yenilir ve yeni hiçbir kod çalıştırılmadığı için DEP ilgisizdir.

Mathias Payer ve Thomas R. Gross tarafından tanıtılan String-Oriented Programming (SOP) ("String Oriented Programming: When ASLR is not Enough"), bunu bir code-reuse saldırısına genelleştirir. Çalışma önce 28C3'te (Aralık 2011) sunulmuş, ardından PPREW'13'te (2013) yayımlanmıştır — bunlar aynı işin iki ayrı etkinlikteki takdimidir. Tek bir payload'ı elle hazırlamak yerine, SOP mevcut binary'deki gadget'ları bulmak için static program analysis kullanır ve o gadget'ları zincirleyen bir dispatcher enjekte etmek (bir jump-oriented-programming tarzı sequencer) için format-string write primitive'ini kullanır. Format string, halihazırda mevcut olan koddan keyfi hesaplama kuran minik bir "program" haline gelir — suistimal edilmesi zor bir saldırı vektörünü güvenilir bir arbitrary code execution'a dönüştürür.

Walkthrough

Üst düzey; herkese açık PPREW'13 makalesini takip eder. SOP, hepsi tek bir format-string bug'ından türetilen üç yeteneği bir araya getirir:

  1. Disclosure — positional read specifier'lar stack canary'sini ve kütüphane/text pointer'larını leak'ler, ASLR ve canary korumasını çökertir.
    // attacker-supplied format string
    "%9$p.%11$p"   // leak a canary and a libc pointer in one shot
    
  2. Write%n-ailesi specifier'lar attacker'ın seçtiği değerleri attacker'ın seçtiği adreslere yazar (yazdırılan karakter sayısı değer olur).
  3. Dispatch — write'lar static (randomize edilmemiş) belleğe bir dispatcher ve bir gadget tablosu yerleştirir; dispatcher tabloyu dolaşır, her gadget'ı sırayla çağırır ve state'i register'lar/bellek üzerinden geçirir — bir data-oriented-programming / JOP döngüsüne benzer.
Neden 'when ASLR is not enough'

Makalenin threat model'i, aynı anda zayıf ASLR + DEP + stack canary'ler içeren bir hedeftir. SOP, tek bir format-string bug'ının üçünü birden aynı anda bypass etmek için yeterli olduğunu gösterir; çünkü her kontrol, bug'ın okuyabileceği veya yazabileceği veri tarafından aracılanır. Static-analysis adımı, chain'in deneme yanılma yerine otomatik olarak kurulduğu anlamına gelir; işte onu tek seferlik bir format-string exploit'inden bir programlama modeline yükselten şey budur.

Sonuç, tamamen binary içi gadget'lardan inşa edilen, enjekte edilmiş hiçbir çalıştırılabilir kod gerektirmeyen ve dönemin standart savunma yığınını tolere eden bir arbitrary code execution'dır.

Detection

  • Güvenilmeyen girdide %n/%hn/%hhn veya alışılmadık derecede yüksek positional index'ler (%30$p) içeren format string'ler temel sinyaldir — bunları application/WAF katmanında logla ve alarm üret.
  • Format argümanı network/kullanıcı girdisinden gelen tekrarlı printf-ailesi çağrıları, özellikle birçok aralık-dışı stack read üretiyorsa, dynamic taint tracking'de ortaya çıkar.
  • static/.data region'larına yapılan anormal write'ları takip eden, o region'lar üzerinden dolaylı control transfer'lar (dispatcher davranışı), CFI-bilinçli EDR tarafından gözlemlenebilir.

Mitigation

  • Derleme zamanında -Wformat -Wformat-security / -Werror=format-security literal olmayan format string'leri reddeder; tüm format-string uyarılarını build-kıran olarak ele al.
  • FORTIFY_SOURCE yazılabilir format string'lerde %n'i kısıtlar (_FORTIFY_SOURCE, yazılabilir bellekte bulunan bir format string'deki %n'i reddeder).
  • Clang CFI / control-flow integrity, dispatcher'ın dolaylı jump'larını bozar; static region'ların ASLR'si (full PIE) tekniğin dayandığı sabit dispatcher/tablo evini kaldırır.
  • Kalıcı düzeltme bug sınıfını ortadan kaldırmaktır: güvenilmeyen veriyi asla bir format string olarak geçirme.

References