Format string write (%n write-what-where)¶
Herhangi bir yere arbitrary değerler yazmak için attacker-controlled bir format string ile %n / %hn kullan.
Mechanism¶
%n yazdırmaz — o ana kadar çıktılanan karakter sayısını, ilgili argüman
slot'undan alınan integer pointer'a yazar. O pointer'ı (attacker buffer'ı
aracılığıyla stack'e yerleştirilen) kontrol ederek ve yazdırılan karakter sayısını
width specifier'larla (%100c) şişirerek, bir saldırgan arbitrary bir adrese arbitrary
bir değer yazar: bir write-what-where primitive.
Note
Length modifier'lar write'ı daraltır: %hn 2 byte, %hhn 1 byte yazar — böylece
tam bir 8-byte pointer, absürt karakter sayılarından kaçınarak birkaç aşamalı kısa
write ile oluşturulur. Direct-parameter erişimi (%7$n) hedef pointer'ı tutan stack
slot'unu tam olarak seçer.
Walkthrough¶
4'üncü argüman slot'unda bir direct-parameter write:
Pratikte pwntools aşamalı %hn/%hhn chain'ini otomatikleştirir:
payload = fmtstr_payload(offset, {location: value})
# offset = stack index where the buffer starts
# writes `value` to `location` via short writes
Beklenen davranış: location adresi (örneğin bir GOT entry, kaydedilmiş bir return
address, .fini_array veya __malloc_hook) value ile overwrite edilir ve bir
control-flow hijack'i mümkün kılar.
Detection¶
-Wformat-security non-literal format'ları işaretler; FORTIFY (-D_FORTIFY_SOURCE=2)
runtime'da writable-format string'lerinde %n'i reddeder. Aşamalı write'lar
istenmeyen memory'yi corrupt ettiğinde crash/abort imzaları belirir.
Mitigation¶
Yalnızca literal format'lar ver. FORTIFY birçok durumda %n'i engeller; Full RELRO
GOT'u read-only yapar (yaygın bir hedefi ortadan kaldırır); ASLR/PIE eşlik eden bir
leak'i zorunlu kılar.