Skip to content

Use of uninitialized variable

Bir stack veya heap variable'ını atanmadan önce okumak; böylece değeri o belleği işgal eden eski byte'lar ne ise odur — bir info leak ya da bir control-flow tehlikesi.

Mechanism

C/C++'ta automatic (stack) ve yeni malloc'lanmış storage sıfırla initialize edilmez; önceki bir frame'in veya allocation'ın geride bıraktığı her şeyi muhafaza eder. CWE-457 sonucu şöyle çerçeveler:

Note

"In languages like C and C++, stack variables lack default initialization and contain junk data from previous stack memory. Attackers may sometimes control or read these contents." — CWE-457

İki ayrı güvenlik sonucu doğar. (1) Information disclosure: uninitialized byte'lar kullanıcıya kopyalanırsa (örneğin bir struct'ı dolduran ama padding/ kullanılmayan alanlara dokunmayan, ardından tüm struct'ı copy_to_user ile gönderen bir kernel ioctl'ü), eski kernel pointer'ları ya da sırlar leak olur — yaygın bir KASLR-defeat primitive'i. (2) Control hazard: uninitialized bir pointer veya uzunluk, bir branch'i ya da bir dereference'i attacker'ın etkileyebileceği eski bir değere doğru yönlendirir.

Walkthrough

CWE-457 control-flow örneği:

char *test_string;
if (i != err_val) {
    test_string = "Hello World!";
}
printf("%s", test_string);   /* if i == err_val, test_string is junk */

i == err_val olduğunda test_string hiç atanmamıştır ve printf("%s", ...) garbage'ı dereference eder. Düzeltme koşulsuz initialization'dır: char *test_string = "Done at the beginning";.

Kernel tarzı padding leak (pratik exploitation biçimi):

struct info {
    u32 a;        /* set */
    /* 4 bytes of implicit padding here -- NEVER written */
    u64 ptr;      /* set */
};
struct info k;
k.a   = x;
k.ptr = y;
/* the 4 padding bytes still hold prior stack contents */
if (copy_to_user(uptr, &k, sizeof(k)))   /* leaks 4 stale kernel bytes */
    return -EFAULT;
MemorySanitizer ile tespit
==12345==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x... in main use_uninit.c:7
  Uninitialized value was created by an allocation of 'test_string'

Detection

MemorySanitizer (-fsanitize=memory) ve Valgrind/memcheck, uninitialized belleğin okunmasını runtime'da işaretler. Linux kernel aynısı için KMSAN kullanır; -Wuninitialized -Wmaybe-uninitialized ile derle. Auto-init mitigation'ları (-ftrivial-auto-var-init=zero, CONFIG_INIT_STACK_ALL_ZERO) hem bunları önler hem de yüzeye çıkarmaya yardımcı olur.

Mitigation

Tanımda initialize et; bir trust boundary'yi geçen struct'ları kısmen doldurmadan önce padding'i açıkça sıfırla (memset(&k, 0, sizeof k)); compiler/kernel'de stack-variable auto-init'i etkinleştir. Tüm object'i kapsayan designated initializer'ları tercih et.

References