Skip to content

Wild pointer write

Değeri uninitialized, eski ya da attacker'ın etkilediği bir pointer üzerinden yapılan, esasen keyfi bir adrese düşen ve orada ne varsa onu corrupt eden bir write.

Mechanism

Bir "wild" pointer, programın asla geçerli bir object adresi olmasını amaçlamadığı bir değer tutar — çünkü uninitialized kullanılmıştır (access-of-uninitialized-pointer), bir free'den sonra dangling bırakılmıştır ya da corrupt/attacker-controlled metadata'dan hesaplanmıştır. Onun üzerinden write yapmak, o sahte adrese veri depolar. Pointer değeri etkilenebilir olduğunda, store yönlendirilmiş bir memory corruption'a dönüşür:

Bir pointer'ın değerini attacker etkileyebildiğinde, write operasyonları keyfi memory location'lara yönlendirilebilir; bu, function return address'leri ya da control-flow bilgisi dahil kritik data yapılarının değiştirilmesine izin verir. (Kök problem CWE-465 / CWE-824; destination kontrol edildiğinde sonuç CWE-123 write-what-where'dir.)

Note

Wild-pointer-write, birçok belirli primitive'in arkasındaki genel biçimdir: destination'ı seçebildiğin (ya da kısmen seçebildiğin) anda, bir arbitrary-write-primitive'e (write-what-where) yükselir. Bir buffer overflow'dan farkı, kötü adresin bilinen bir buffer'ın sonundan taşmaktan değil, pointer değerinin kendisinden gelmesidir. Kök problem invalid/uncontrolled bir pointer value'dur: CWE-465 (Pointer Issues) ve CWE-824 (Uninitialized Pointer Dereference). Destination attacker-controlled olduğunda somut sonuç CWE-123 (Write-What-Where Condition); wild write bilinen bir buffer'ın OOB bölgesine denk geldiğinde ise CWE-787 (out-of-bounds write)'tır.

Walkthrough

Uninitialized-pointer write (değer stack garbage'ıdır):

void f(int set, char *src) {
    char *dst;                 /* uninitialized -- holds stale stack bytes */
    if (set) dst = real_buf;
    /* attacker arranges !set */
    memcpy(dst, src, 32);      /* writes 32 bytes to a wild address */
}

Attacker-controlled pointer → write-what-where:

struct node { long *where; long what; };
/* corrupt node->where via an earlier overflow/UAF, then: */
*n->where = n->what;           /* stores chosen value at chosen address */

Tek bir controlled wild write tipik olarak yüksek değerli bir hedefe nişan alır — bir saved return address, bir GOT/PLT entry (got-plt-overwrite), bir function pointer ya da allocator metadata — tek bir write'ı control-flow hijack'e dönüştürür.

Bir wild/out-of-bounds store için ASan raporu
==5151==ERROR: AddressSanitizer: SEGV on unknown address 0x000041414141
    WRITE of size 8 at 0x000041414141 thread T0
    #0 0x... in f wild.c:7
AddressSanitizer can not provide additional info (the address is wild).

Detection

ASan/KASAN çoğu out-of-object write'ı yakalar; "wild" durumu çoğu zaman non-canonical/garbage bir adreste bir SEGV olarak kendini gösterir. MSan, uninitialized pointer'lar üzerinden yapılan write'ları işaretler; statik analiz (-Wuninitialized, clang-analyzer, Coverity) bariz uninitialized-dst biçimini yakalar. CFI/RELRO, control verisini hedeflediğinde başarılı bir write'ı tespit edilmiş bir ihlale dönüştürür.

Mitigation

Her pointer'ı initialize et (ideal olarak NULL'a) ve free'den sonra null'la; write'tan önce destination pointer'ları/offset'leri amaçlanan object'e karşı doğrula; full RELRO GOT'u read-only yapar; CET shadow stack'ler saved return address'leri korur; memory-safe diller ya da bounds-checked container'lar bu sınıfı ortadan kaldırır.

References