_IO_wfile_jumps¶
Forge edilmiş bir FILE'ın vtable'ını in-range
_IO_wfile_jumps'a ayarla ve_IO_wfile_overflow'u tetikle ki_IO_wdoallocbufattacker-controlled bir_wide_data->_wide_vtable'ı dereference etsin (House of Apple 2).
Mechanism¶
Note
_IO_wfile_jumps, wide-character file stream'lerin vtable'ıdır ve __io_vtables
içinde durur, dolayısıyla ona yönelen forge edilmiş bir FILE glibc 2.24 range check'ini
geçer. _IO_wfile_overflow'u tetiklemek şunu çalıştırır: wide write buffer
unallocated ise (fp->_wide_data->_IO_write_base == NULL) _IO_wdoallocbuf(f)'i çağırır,
o da _IO_WDOALLOCATE(fp) macro'sunu invoke eder →
fp->_wide_data->_wide_vtable->__doallocate'i dereference eder. Kritik nokta: _wide_data
ve onun ikincil _wide_vtable'ı _IO_vtable_check range test'ine tabi değildir.
__doallocate slot'u system olan, tamamen attacker-controlled bir _wide_vtable
(FILE/buffer öyle ayarlanmış ki argument "/bin/sh" olur) arbitrary bir call verir —
bu, baskın modern FSOP technique'i olan House of Apple 2'nin çekirdeğidir.
Walkthrough¶
Erişilebilir path (glibc libio/wfileops.c, wgenops.c):
wint_t _IO_wfile_overflow (FILE *f, wint_t wch) {
...
if (f->_wide_data->_IO_write_base == NULL) {
_IO_wdoallocbuf (f); /* if wide buffer unallocated */
...
}
}
void _IO_wdoallocbuf (FILE *fp) {
if (fp->_wide_data->_IO_buf_base) return;
if (!(fp->_flags & _IO_UNBUFFERED))
if ((wint_t) _IO_WDOALLOCATE (fp) != WEOF) /* -> _wide_vtable->__doallocate */
return;
...
}
/* _IO_WDOALLOCATE(fp) == fp->_wide_data->_wide_vtable->__doallocate(fp) */
House of Apple 2 reçetesi:
vtable = &_IO_wfile_jumps(in range; check'i geçer, bkz. io-vtable-check-bypass.md) olan bir FILE forge et._flags'i öyle ayarla ki_IO_UNBUFFEREDclear olsun ve overflow/_wdoallocbufpath'i çalışsın;_wide_data'yı_IO_buf_base == NULLve_IO_write_base == NULLolan kontrollü bir region'a ayarla._wide_data->_wide_vtable'ı__doallocateentry'sisystemolan fake bir table'a yönelt ve"/bin/sh"'e bir pointer'ı,fp'nin (ilk argument) call'ı faydalı kıldığı yere yerleştir (genelde_flagsfield'ının" sh;"tarzı string'lerle overlap etmesi yoluyla).exit/abort sırasında_IO_flush_all_lockpüzerinden tetikle (fsop-via-io-list-all-io-flush-all-lockp.md).
Warning
_wide_data'nın field offset'leri ve _wide_vtable slot index'i glibc versiyonları
arasında değişir; target libc'ye karşı doğrula. Bazı 2.36+ hardening'ler wide path'in
parçalarını pointer-guard'lar.
Detection¶
_IO_wdoallocbuf/_IO_WDOALLOCATE'ten non-allocator bir adrese giden indirect call.- Flush list'inde
_IO_wfile_jumpskullanan, heap'e işaret eden bir_wide_vtable'a sahip FILE.
Mitigation¶
- 2.24 range check'i
_wide_vtable'ı kapsamaz; sonraki glibc wide path'in parçalarına guarding ekler. İkincil vtable call'u üzerindeki CFI yapısal çözümdür.