House of Einherjar¶
Off-by-null backward consolidation: PREV_INUSE'u temizleyip prev_size'ı forge ederek bir chunk'ı attacker-controlled bir fake chunk'a coalesce etmek.
Mechanism¶
Bir off-by-one / off-by-null overflow, sonraki chunk'ın size field'ındaki PREV_INUSE bit'ini
temizler ve allocator'ı önceki chunk'ın free olduğuna inandırır. free() sırasında bu
backward consolidation'ı tetikler: malloc önceki chunk'ı,
attacker-controlled bir prev_size kullanarak chunk_at_offset(p, -((long) prev_size)) olarak hesaplar. Bu,
consolidate edilen chunk'ın bir fake chunk'a inmesine izin verir ve arbitrary (overlapping) bir
allocation verir.
Note
Köken: Hiroki Matsukuma, 2016. shellphish how2heap'te glibc 2.23–2.39 boyunca gösterildi.
Kendine referans veren fd = bk = &fake hilesi, klasik
unlink fd/bk validation'ından kaçan şeydir.
Walkthrough¶
a (attacker-controlled), b, c chunk'larıyla:
a[2] = a; a[3] = a; // fake chunk: fd = bk = &fake, passes unlink checks
// set fake chunk size to match the forged prev_size
b[real_b_size] = 0; // off-by-null: clears c's PREV_INUSE
// write forged prev_size into b's trailing prev_size slot
// = distance from c back to the fake chunk
free(c); // consolidates backward onto the fake chunk
Modern glibc'de (tcache mevcut) önce o boyut için tcache'i doldurmalısın ki
free(c), tcache yerine unsorted-bin/consolidation yoluna ulaşsın. Sonuç: sonraki bir
malloc, fake-chunk bölgesine (örn. stack'in üzerine) bir pointer döndürür ve arbitrary
write verir.
Warning
prev_size, c'den fake chunk'a olan offset'e tam olarak eşit olmalıdır; modern glibc
onu hesaplamak için de genelde bir heap leak gerektirir.
Mitigation¶
glibc'nin unlink'i chunksize(P) != prev_size(next_chunk(P))'yi (corruption-of-size
check'i) zorunlu kılar. Sonraki glibc, prev_size-vs-size consistency check'ini ve tcache count/key
check'lerini ekler, gereksinimleri yükselterek. Bkz. off-by-null-poison-null-byte ve unsafe-unlink.