FSOP via _IO_list_all / _IO_flush_all_lockp¶
exit/abort sırasında glibc,
_IO_flush_all_lockpiçinde_IO_list_allstream chain'ini dolaşır ve her FILE'ın vtable'ı üzerinden_IO_OVERFLOWçağırır;_IO_list_all'ı sahte bir FILE'a overwrite etmek kontrollü bir vtable call sürer.
Mechanism¶
Note
File Stream Oriented Programming (FSOP), glibc'nin normal teardown'unu suistimal
eder. exit() sırasında, main'den dönüşte veya abort() sırasında, _IO_cleanup
→ _IO_flush_all_lockp singly-linked _IO_list_all listesini (her FILE'ın _chain'i
üzerinden) iterate eder ve pending output'u olan herhangi bir stream için
_IO_OVERFLOW(fp, EOF)'u vtable üzerinden çağırır. Security boundary, stream
listesinin ve dispatch ettiği vtable'ın bütünlüğüdür. _IO_list_all'ı (klasik olarak
bir unsorted-bin veya large-bin attack ile) writable memory'deki sahte bir
_IO_FILE_plus'a işaret edecek şekilde overwrite ederek saldırgan, process
teardown'ında hangi object'in — ve hangi vtable'ın — invoke edileceğini kontrol eder,
ek bir trigger gerekmeden.
Walkthrough¶
Ulaşılabilir koşul (glibc libio/genops.c, _IO_flush_all_lockp):
for (fp = (FILE *) _IO_list_all; fp != NULL; fp = fp->_chain)
if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base))
&& _IO_OVERFLOW (fp, EOF) == EOF) /* vtable dispatch */
result = EOF;
Kavramsal tarif:
- libc base'i ve bir arbitrary write (veya bir bin-attack write primitive) elde et.
_IO_list_all'ı heap'teki sahte bir FILE'a işaret edecek şekilde overwrite et.- Sahte FILE'da flush koşulunun geçmesi için
_mode <= 0ve_IO_write_ptr > _IO_write_baseayarla. - Sahte
vtable'ı_IO_OVERFLOWsaldırgan koduna resolve olacak şekilde ayarla — 2.24 öncesi doğrudan; 2.24 sonrası bir vtable-range bypass ile birleştir (file-vtable-hijack.md, House of Apple). - Normal
exit/abortveyamainreturn ile tetikle —_IO_cleanup→_IO_flush_all_lockplistesini yürür ve sahte FILE'ın_IO_OVERFLOW'unu vtable üzerinden dispatch eder. (House of Orange, bu_IO_list_alloverwrite'ını bir unsorted-bin attack ile sağlayan ayrı bir primitive'tir — corrupt bir top chunk üzerindenmalloc'taabort'u zorlar; ama bu primitive için şart değil, large-bin attack vb. de_IO_list_alloverwrite'ı için kullanılabilir.)
Warning
glibc 2.24'ten beri naif "vtable = system" yaklaşımı _IO_vtable_check tarafından
engellenir; modern FSOP bunu in-range bir vtable (_IO_str_jumps/_IO_wfile_jumps)
ile eşleştirir.
Detection¶
vtable'ı__libc_IO_vtablesdışında olan veya alanları gerçek bir stream ile tutarsız olan heap-resident FILE struct'ları.- Bilinen stdio FILE'larına referans vermeyen
_IO_list_allhead veya_chainpointer'ları. _IO_list_alladresini hedefleyen unsorted/large-binbk/fdwrite'ları.
Mitigation¶
- glibc 2.24+ vtable whitelist'i (
_IO_vtable_check) naif sahte vtable'ları engeller. - Heap-integrity hardening (tcache/unsorted-bin check'leri, safe-linking)
_IO_list_all'ı overwrite eden write primitive'ini azaltır. - Full RELRO/ASLR ve info-leak önleme.