POC详情: c274b391ffbb730808ee383fb4c48aabe3fea67d

来源
关联漏洞
标题: Linux kernel 安全漏洞 (CVE-2016-6187)
描述:Linux kernel是美国Linux基金会发布的开源操作系统Linux所使用的内核。NFSv4 implementation是其中的一个分布式文件系统协议。 Linux kernel 4.6.5之前的版本中的security/apparmor/lsm.c文件中的‘apparmor_setprocattr’函数存在安全漏洞,该漏洞源于程序没有验证缓冲区大小。本地攻击者利用该漏洞获取权限。
描述
Kernel Exploit PoC for CVE-2016-6187 (Local Privilege Escalation)
介绍
# CVE-2016-6187 - Linux Kernel Exploit
[![asciicast](https://asciinema.org/a/jdctd18rbPq9unFsWAtPplUnI.svg)](https://asciinema.org/a/jdctd18rbPq9unFsWAtPplUnI)

Kernel Exploit for CVE-2016-6187 (Local Privilege Escalation) (affected versions: < 4.6.5)

Exploit was developed against a custom compiled 4.6 kernel + buildroot (kconfig coming soon)
and defeats ```KASLR```, ```SMEP```, ```SMAP``` (```KPTI``` not available for 4.6)

## Vulnerability Details
The exploited vulnerability is a heap based single nullbyte overflow in one of AppArmor's LSM hooks (setprocattr). See https://nvd.nist.gov/vuln/detail/CVE-2016-6187

## Exploit

### Reliability
Initial measurements indicate a 94.44% chance of spawning a root shell. In 1 out of 18 cases,
the exploit will oops the kernel. Further work is needed to fully stabilize the kernel after gaining root access.

### Technique
We abuse the nullbyte overflow to corrupt the LSB of a freelist pointer in ```kmalloc-128```, effectively letting
it point to an already allocated object. After that, we free that allocated object, causing a double free scenario.

Now we can allocate two overlapping structures from the ```kmalloc-128``` cache. The first structure is an object
with content that can be read back by userspace. For that, I have chosen ```ip6_sf_socklist```. The second structure,
which will be allocated on top of ```ip6_sf_socklist``` should contain kernel pointers - ```rfkill_data``` is a good fit.
It contains a heap pointer (empty ```rfkill_data.events``` list) and a global data pointer to ```rfkill_fds``` (```rfkill_data.list.prev```).
Once ```rfkill_data``` is allocated on top of ```ip6_sf_socklist```, we can retrieve the kernel pointers by calling
```getsockopt(sock, IPPROTO_IPV6, MCAST_MSFILTER, gsf, &optlen)```. The kernel text base can then be derived from ```rfkill_fds```.

We then cause a second double free scenario, but this time we abuse the message queue's linking process to overwrite the freelist pointer
and trick the allocator to return us a chunk from ```kmalloc-96``` when we actually request a chunk from ```kmalloc-128```.

We can then leverage the size mismatch to overflow into the freelist pointer of a ```kmalloc-96``` chunk, giving us the primitive to
allocate arbitrary addresses. In our case, we go for the ```ptmx_fops``` structure and overwrite the ```ptmx_fops.unlocked_ioctl```
callback with a pointer to our stack pivot gadget.

Calling ```ioctl``` on ```/dev/ptmx``` triggers the pivot gadget and we pivot the stack to a fake stack in ```kmalloc-128``` where we
already prepared our first stage rop chain.

Since we have limited space on the ```kmalloc-128``` fake stack (we don't know if the next chunk will be on the same ```slab```), the task
of the first stage rop chain is to copy the second stage rop chain from userspace into the kernel dmesg log buffer (```__log_buf```)
and to pivot the stack to ```__log_buf```.

The second stage rop chain then tries to repair the kernel (restoring ```ptmx_fops```, ...) before it calls ```commit_creds(prepare_kernel_cred(NULL))```
to escalate privileges.

And finally it exits the kernelspace via ```iretq``` and we return, with elevated privileges, to our ```execve("/bin/sh", 0, 0)``` subroutine.

## Requirements

### /dev/rfkill
Unprivileged users must be able to at least open ```/dev/rfkill```. Some distros might
not permit that. I have checked Ubuntu and Fedora, both allow unprivileged users to open ```/dev/rfkill```
(although Fedora is using SELinux instead of AppArmor)

## Reproducing the Exploit

The following section explains how to reproduce the local privilege escalation in ```qemu-x86_64```.

First, you will have to obtain an ```initrd``` and ```bzImage``` kernel. There are two ways:

### Method 1: Prebuilt

The easiest and quickest way. You can find all the required components in ```prebuilt/```.

### Method 2: DIY

Or, alternatively, you could also build the components yourself. Simply fetch the
[4.6 kernel](https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.6.tar.xz) and use
the provided ```x86_64_vuln_kern_defconfig``` in ```config/``` to compile the ```bzImage```.

For the ```initrd``` you could, for example, use [buildroot](https://www.buildroot.org/). Just make
sure to set the correct permissions for ```/dev/rfkill``` in your ```init```

```bash
chmod 664 /dev/rfkill
```

This is the same as in ```Ubuntu-16.04``` and many other distros. Also do not forget to compile
the exploit and put it into your ```initrd```

```console
make
```

### Dropping a root shell

Once you have obtained the components, boot the vulnerable machine
```
./boot.sh <path/to/bzImage> <path/to/rootfs.cpio>
```
and execute the exploit
```
./exploit
```
You may need to run the exploit several times, depending on whether we have nulled out
a LSB that was already zero. Also note, that there is still a slight chance (maybe 10%-20%?) of
crashing after gaining root access - I am working on it.

Have fun.

## TODO's

- [x] repair ```ptmx_fops``` to increase stability
- [ ] repair ```kmalloc-128``` freelist to increase stability
- [ ] repair message queue to increase stability
- [ ] automatically restart exploit when detecting failure
- [ ] add proper writeup
- [x] publish kconfig, build instructions, ...
- [ ] code refactoring/cleanup
文件快照

[4.0K] /data/pocs/c274b391ffbb730808ee383fb4c48aabe3fea67d ├── [ 442] boot.sh ├── [4.0K] config │   └── [6.8K] x86_64_vuln_kern_defconfig ├── [ 25K] exploit.c ├── [ 204] Makefile ├── [4.0K] prebuilt │   ├── [6.3M] bzImage │   └── [5.8M] rootfs.cpio └── [5.2K] README.md 2 directories, 7 files
神龙机器人已为您缓存
备注
    1. 建议优先通过来源进行访问。
    2. 如果因为来源失效或无法访问,请发送邮箱到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
    3. 神龙已为您对POC代码进行快照,为了长期维护,请考虑为本地POC付费,感谢您的支持。