The Road To Linux Kernel Exploit

2018-11-22

菜鸡学kernel exploit

关闭kaslr、smap

sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="quiet"/GRUB_CMDLINE_LINUX_DEFAULT="quiet nokaslr nosmap"/g' /etc/default/grub

install systemtap

# 安装带调试符号的内核文件
# http://ddebs.ubuntu.com/pool/main/l/linux/linux-image-4.4.0-62-generic-dbgsym_4.4.0-62.83_amd64.ddeb

wget http://ddebs.ubuntu.com/pool/main/l/linux/linux-image-4.4.0-62-generic-dbgsym_4.4.0-62.83_amd64.ddeb
sudo dbkg -i linux-image-4.4.0-62-generic-dbgsym_4.4.0-62.83_amd64.ddeb
sudo apt install systemtap

# test if ok
stap -v -e 'probe vfs.read {printf("read performed\n"); exit()}'

安装指定版本内核

# search for usable version
apt-cache  search linux|grep linux-image|grep 4.4.0-62
apt-cache  search linux|grep linux-header|grep 4.4.0-62
# install kernel image&header
apt install linux-image-4.4.0-62-generic
apt install linux-headers-4.4.0-62-generic

# display grub boot menu
sed -i 's/GRUB_HIDDEN_TIMEOUT=0/GRUB_HIDDEN_TIMEOUT=8/g' /boot/grub
sed -i 's/GRUB_HIDDEN_TIMEOUT_QUIET=true/GRUB_HIDDEN_TIMEOUT_QUIET=false/g' /boot/grub
update-grub

卸载指定版本内核

dpkg --list|grep linux-image
sudo apt-get purge linux-image-3.19.0-15
sudo apt-get purge linux-headers-3.19.0-15

内核源码获取

understand - mac下优秀的源码阅读器

在审计源码之前,推荐一款mac下优秀的源码阅读器understand,它有一些非常有利于编写poc的功能:

  • 查看当前函数被引用情况
  • 列出当前函数引用情况
  • 生成当前函数的控制流图

获取某个版本源码

https://launchpad.net/ubuntu/xenial/+package/linux-source-4.4.0 上可以找到某个版本、某个patch的deb包,解压即可。

以cve-2017-11176为例

对已知漏洞的分析流程

一般步骤

  1. 理解patch代码、注释
  2. 梳理漏洞原理
  3. 利用systemtap来验证实现的可能性
  4. 尝试在没有systemtap时如何满足利用条件

一些公开信息

查看patch说明 kernel/git/torvalds/linux.git - Linux kernel source tree

mqueue: fix a use-after-free in sys_mq_notify()
The retry logic for netlink_attachskb() inside sys_mq_notify()
is nasty and vulnerable:

1) The sock refcnt is already released when retry is needed
2) The fd is controllable by user-space because we already
   release the file refcnt

so we when retry but the fd has been just closed by user-space
during this small window, we end up calling netlink_detachskb()
on the error path which releases the sock again, later when
the user-space closes this socket a use-after-free could be
triggered.

Setting 'sock' to NULL here should be sufficient to fix it.

Reported-by: GeneBlue <geneblue.mail@gmail.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Manfred Spraul <manfred@colorfullife.com>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

mq_notify中的一个uaf漏洞。

该漏洞成因

diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index c9ff943f19ab..eb1391b52c6f 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -1270,8 +1270,10 @@ retry:
 
 			timeo = MAX_SCHEDULE_TIMEOUT;
 			ret = netlink_attachskb(sock, nc, &timeo, NULL);
-			if (ret == 1)
+			if (ret == 1) {
+				sock = NULL;
 				goto retry;
+			}
 			if (ret) {
 				sock = NULL;
 				nc = NULL;

进入retry逻辑之前未把引用计数为0的sock清除,而对应的fd为用户可控数据。产生了一个可触发的悬垂指针。

利用systemtap验证可行性

  1. 找到所以触发该漏洞需要的条件
  2. 在systemtap脚本中给相应数据赋值以满足利用条件
  3. 运行systemtap脚本并执行简易poc

值得探讨的地方

We might actually create multiple message queues, hence multiple mqueue_inode_info objects and call mq_notify() multiple times. Or, we can also use mq_timedsend() syscall to push messages into the queue. Because we don’t want to study another subsystem (mqueue), and stick with “common” kernel path (sendmsg), we won’t do that here. It might be a good exercise though…

查看reference #1

使用systemtap时的一些报错

  • error: ISO C90 forbids mixed declarations and code
    /tmp/stapKh6ZFj/stap_3b5bf6ba7089b1fa505f041e246d67e5_425053_src.c:5622:5: error: ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]
       struct files_struct *files = (void*)current->files;
    

reason: printf,printk could not appear before var define

reference

  1. https://blog.lexfo.fr/
  2. A Guide to Kernel Exploitation Attacking the Core
  3. linux内核揭秘