FILE vtable hijack (_IO_validate_vtable bypass)¶
Bir FILE'ın vtable'ını legitimate in-range bir jump table'a (örn.
_IO_str_jumps) işaret ettir; böylece glibc'nin_IO_validate_vtablesection check'ini geçer, handler'ı ise attacker-controlled ikincil bir call'a ulaşır.
Mechanism¶
Note
glibc 2.24, _IO_vtable_check / IO_validate_vtable'ı ekledi: herhangi bir
vtable dispatch'inden önce FILE'ın vtable pointer'ı read-only
__libc_IO_vtables section'ı içinde bulunmalıdır (bu section'daki array
symbol'ü sibling notlarda geçen __io_vtables'tır; sınır kontrolü vtable -
__start___libc_IO_vtables < section boyutu), aksi halde slow path
__libc_fatal üzerinden abort eder. Güvenlik sınırı "yalnızca kutsanmış
vtable'lar çağrılabilir"dir. Bypass, sıfırdan yeni bir vtable forge etmez;
handler'ı ardından FILE'ın attacker-controlled bir field'ı üzerinden ikinci,
check'lenmemiş bir indirect call yapan gerçek bir in-range tabloyu yeniden
kullanır. Örneğin _IO_str_jumps→_IO_str_overflow, fp+0xe0'daki allocator
pointer'ını çağırır ve _IO_str_finish fp+0xe8'i çağırır; wide tablo
_IO_wfile_jumps, _wide_data->_wide_vtable'a ulaşır (House of Apple 2). Range
check geçer çünkü primary vtable legitimate'tir; control flow, check'in asla
kapsamadığı ikincil dispatch'te çalınır.
Walkthrough¶
Ulaşılabilir biçim (glibc libio/strops.c, genops.c):
/* _IO_str_overflow effectively calls: */
new_buf = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);
/* _allocate_buffer lives at fp+0xe0, not range-checked */
Kavramsal reçete:
- libc'yi leak'le;
&_IO_str_jumps'ı hesapla (in-range, check'i geçer). - Forge edilmiş/corrupt edilmiş FILE'ın
vtable = &_IO_str_jumps'ını set et. - Operasyonu/flush'ı,
_IO_str_overflow(ya da_IO_str_finish) dispatch edilen slot olacak şekilde düzenle. - Gömülü function pointer'ını (
fp+0xe0/fp+0xe8)system/one_gadget'a set et ve arg'ı şekillendir (örn. bir"/bin/sh"pointer'ı). - FILE-flush path'i üzerinden tetikle (fsop-via-io-list-all-io-flush-all-lockp.md).
Warning
Field offset'leri ve tam olarak ulaşılabilir handler glibc sürümüne göre
değişir; sonraki release'ler _IO_str/wide path'lerinin parçalarını
sertleştirdi. Target libc'ye karşı doğrula.
Detection¶
- Program'ın bir string/wide stream olarak hiç oluşturmadığı,
_IO_str_jumps/_IO_wfile_jumpstaşıyan heap-resident bir FILE. .textdışına işaret eden ikincil dispatch (fp+0xe0,_wide_vtable).- Başarısız bir vtable check'inde tetiklenen
__libc_fatal/abort (probing göstergesi).
Mitigation¶
__libc_IO_vtables'ı read-only tut (zaten enforce ediliyor) ve validation'ı ikincil dispatch pointer'larına genişlet.- libio indirect call'ları üzerinde CFI /
-fcf-protection. - ASLR ve info-leak önleme;
_IO_str/wide overflow handler'larını sertleştir.