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:
- Disclosure — positional read specifier'lar stack canary'sini ve kütüphane/text pointer'larını leak'ler, ASLR ve canary korumasını çökertir.
- 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). - 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/%hhnveya 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/
.dataregion'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-securityliteral 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.