Skip to content

Arbitrary call via UAF

Bir function pointer gömen bir kernel objesini free et, slot'unu attacker'ın kontrol ettiği data ile reclaim et, sonra indirect call'u tetikleyerek RIP kontrolü elde et.

Mechanism

Note

Bir function pointer (bir ops table pointer'ı ya da bir callback) içeren bir obje üzerindeki use-after-free, attacker (1) bir dangling reference kalırken objeyi free ettiğinde, (2) freed slot'u aynı kmalloc size'da kontrol edilen byte'larla reclaim ettiğinde ve (3) corrupt edilen pointer üzerinden indirect/virtual call yapan code path'ini sürdüğünde RIP kontrolüne dönüşür. Invariant, size eşlemesidir: reclaim objesi free edilen obje ile aynı kmalloc cache'ine düşmeli ki function pointer'ı örtsün.

Walkthrough

Kanonik bir target, 0x400-byte'lık bir driver buffer'ı üzerindeki bir UAF ile ulaşılan tty_struct'tır (kmalloc-1024):

int magic;                          /* off 0x00, must stay 0x5401 */
struct kref kref;
struct device *dev;
struct tty_driver *driver;
const struct tty_operations *ops;   /* off 0x18  <-- hijack target */

Akış: fd1'i aç (buffer'ı allocate eder), fd2'yi aç (aynı pointer'ı reallocate eder), fd2 dangle ederken free etmek için close(fd1). Slot'u, ops'u kontrol edilen bir tty_operations table'ına işaret eden sahte bir tty_struct ile reclaim et; sonra tty üzerinde ioctl() çağırarak 12 * sizeof(uint64_t) slot'undaki function pointer'ı kontrol edilen cmd/arg ile fire et.

SMEP/SMAP sahte table'ı ve ROP chain'i kernel memory'sinde yaşamaya zorladığı için, önce tty_struct->ops'u (sabit bir offset'te .rodata'ya işaret eder) leak ederek kernel base'i kurtar ve spray'lenen chain'in nerede oturduğunu öğrenmek için bir msg_msg heap-address leak'i kullan. Sonra ops->ioctl'i bir stack-pivot gadget'ı olarak sahtele:

0x14fbea: push rdx; xor eax, 0x415b004f; pop rsp; pop rbp; ret;
ioctl(tty_fd, 0xcafebabe, rop_addr - 8);  /* rdx = rop_addr - 8 -> pivot RSP onto ROP */

Warning

Corrupt edilen objenin close/shutdown/cleanup pointer'larını bir ret gadget'ına ayarla; aksi halde obje teardown garbage'ı dereference eder ve kernel'i panic'ler (ve saldırının sinyalini verir).

Detection

Gereken leak + spray + indirect-call dizisi (örn. tty allocation, msg_msg address leak'leri, olağandışı bir ioctl cmd'i) tespit edilebilir; düzgün ret stub'ları olmadan teardown'dan gelen bir panic, gürültülü bir sinyaldir.

Mitigation

  • SMEP, userspace shellcode'a bir jump yerine ROP'u zorlar; SMAP kernel'in userspace'i dereference etmesini engeller, dolayısıyla sahte ops table'ı ve chain kernel memory'sinde olmalıdır.
  • KASLR, herhangi bir gadget adresi kullanılabilir olmadan önce ops leak'ini zorlar.
  • CFI (forward-edge control-flow integrity), uyumsuz target'lara yapılan indirect call'ları reddederek hijack edilen call'u kırar. Slab freelist randomization ve hardened freelist pointer'ları reclaim güvenilirliğini düşürür.

References