Skip to content

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

snprintf(buf, 128, argv[1]);   // CWE-134: user-controlled format string

4'üncü argüman slot'unda bir direct-parameter write:

%4$n

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.

References