关联漏洞
标题:
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
[](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付费,感谢您的支持。