Skip to content

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.

References