Linux内核Waitid系统调用本地提权漏洞(CVE-2017-5123)的分析与利用
最近在整理Linux内核漏洞利用的一些场景,比如利用系统调用漏洞、利用一些比较容易fuzz的漏洞,通过对这类场景的总结可以帮助我们快速发现0day,积累漏洞挖掘的经验。虽然这一类型的漏洞出现的频率很低但是优点也很显著,这类漏洞利用比较简单、直接。我通过查看github上Linux源代码patch日志发现CVE-2017-5123就是我要收集的目标,这类漏洞的攻击面是内核处理用户态指针出错,一般是内核没有检查用户态指针就直接使用,或者是对用户态指针检查不正确(本来是用来read的指针,却用来write)等, 一般会在access_ok、copy_from_user、copy_to_user 等几个函数使用中出现漏洞。
著名exploit网站Exploit Database对于CVE-2017-5123的介绍
链接地址:https://www.exploit-db.com/exploits/43029/
漏洞针对的Linux内核版本: Linux version 4.14.0-rc4+ (fuzz@ns388631) (gcc version 7.1.1 20170621 (GCC)) #1 SMP Mon Oct 16 21:54:35 CEST 2017
Android系统不受此漏洞影响。
0×1 测试环境在virtualbox虚拟机ubuntu 14.04上测试。测试流程和视频中完全一样。
https://asciinema.org/a/BeRNWtrX27yF28CMeflqHQT0H
(exploit代码不是在Host系统中测试,通过qemu挂载有漏洞的kernel和filesystem 镜像测试exploit)
0×2 漏洞原理漏洞出现在waitid系统调用中,因为没有检查用户态传入的指针的有效性导致用户态可以任意内核地址写漏洞。
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
patch是调用access_ok检查infop参数的有效性。
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=96ca579a1ecc943b75beba58bebb0356f6cc4b51
patch中添加了检查参数infop用户态指针是否可以写入的检测。如果infop指向无效地址, 或者内核地址空间都是非法的。
0×3 Exploit 分析在github上有人提供了一份利用内核任意地址写漏洞本地提权的exploit,要执行此 exploit 必须关闭mmap_min_addr 和 SMEP 防护。
这份exploit 比较简单,学习的重点放在如何修改的内核内存达到劫持控制流。
首先exploit从内核符号表获取了commit_creds,prepare_kernel_cred函数的地址。 commit_creds(cred *)函数可以更新当前进程的cred凭据。prepare_kernel_cred()函数可以创建一个凭据。
接下来申请一片内存用来存储shellcode。这里从0地址开始映射了4096 byte内存。
这里先是向0xffffffff81f3f45a 地址写入0, 然后跳转到get_root 函数处去刷新当前进程的 凭据, 刷新凭据的代码使用通用的提权代码,如下:
上述权限提升有效载荷会分配一个新的凭证结构(uid=0, gid=0等)并将它应用到调用进程中, 当前这个exploit就是使用的这个payload达到提权的目的。因为关闭SMEP所以免去了用rop翻转smep绕过SMEP的限制。
最后该触发漏洞漏洞了,这里先调用waitid(1, pid,0xffffffff81f3f45a,…)修改内核地址0xffffffff81f3f45a的内容,然后调用fork函数。一般的套路是修改内核data段内一个全局结构体中的函数指针地址,然后在调用此函数指针跳转到我们的目标地址。
内核中有很多这样的结构,比如avc_callbacks、cgroup_subsys、have_fork_callback 等等。这里作者只给了一个地址没有说明是那个函数,需要动态调试内核到这个地址查看内容才能知道使用的是哪个函数指针。
目前受到网络影响没办法调试漏洞,暂且分析作者的调试日志,可以发现漏洞触发过程的调用栈。
Trace:[ 6.371828] ? cgroup_can_fork+0×63/0xb0
[ 6.372082] copy_process.part.55+0x115f/0x19e0
[ 6.372328] _do_fork+0xbd/0×370
[ 6.372454] SyS_clone+0×14/0×20
[ 6.372560] do_syscall_64+0x4e/0×100
[ 6.372669] entry_SYSCALL64_slow_pat
根据调用栈 我们就知道是修改了fork函数实现中的某个函数指针,下面继续分析源代码。
(linux/kernel/cgroup/cgroup.c)
cgroup_subsys结构体数组是一个全局变量伴随内核启动初始化完毕,这里调用cgroup_subsys结构体中的can_fork函数指针,所以可以猜测 0xffffffff81f3f45a地址就在 cgroup_subsys对象附近。
再来看下waitid是如何写入0到0xffffffff81f3f45a地址。
waitid中多处调用unsafe_put_user()向infop指针(0xffffffff81f3f45a)写入数据。
exploit中调用完waitid紧接着调用了fork函数触发了can_fork函数跳转到0地址执行shellcode。
漏洞分析和exploit的原理分析完毕,我在本地做了测试非常稳定的exploit,感兴趣可以看看文章开头的提权视频。
0×4 exploit 代码说明 exploit 执行exploit代码执行顺序:
1、run_kernel.sh在qemu中启动vul linux(开启靶场),从qemu 启动日志和脚本可以看到系统防护的状态(NX开启了,kaslr关闭了)
2、setup_exploit.sh在1执行完以后,当前的终端会进入vul linux系统,此时是root 用户。此脚本会关闭mmap_min_addr限制允许exploit mmap 0地址,并输出”./exploit 0xffffffff81f3f45a”。这里要启动一个普通用户,准备提升权限。
3、./exploit 0xffffffff81f3f45a在2中输出了这条命令,exploit是二进制程序没有源代码,可以逆向或者自己分析漏洞写exp。此exp已经具有任意内核地址写的能力。
编译kernel filesystem方法kernel和filesystem的编译方法在 kernel_compilation_cheatsheet.md文件中。
exploit 代码:
https://github.com/nongiach/CVE/tree/master/CVE-2017-5123
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/54705.html
AndroidlinuxshellUbuntuVirtualBox虚拟机相关文章
- window与linux项目部署之linux文件路径不存在问题
- 探索Linux内核之旅(linux内核镜像)
- 漏洞分析Linux服务端代码漏洞:深度分析与防护(linux服务端代码)
- 优化Linux内核参数,提升系统性能(linux的内核参数优化)
- Linux内核网络编程:构建高效可靠互联系统(linux内核网络编程)
- 马哥Linux助力老男孩重现辉煌(马哥linux与老男孩)
- 嵌入式技术:精简Linux内核的新方法(嵌入式linux内核裁剪)
- Linux驱动加载:深入解析(linux如何加载驱动)
- Linux内核分析与高级编程技巧(linux内核分析及高级编程)
- 红帽Linux:实现安全且强大的计算机(红帽linux有什么用)
- Linux漏洞安全检测:威胁识别与防护(linux漏洞检测)
- 探索 Linux 系统日志查询命令(查看linux日志命令)
- 【Linux系统关闭防火墙】(关闭linux的防火墙)
- 存在多年的 Linux 漏洞被发现:可通过 WiFi 攻击目标计算机
- 学习Linux?这里有一些精品视频教程推荐!(linux系统视频教程)
- 探究Linux内核堆管理机制(linux内核堆)
- 优化Linux内核参数配置,提升效率(linux内核参数配置)
- 解除Linux内核:释放系统的自由(删除linux内核)
- 利用Linux实现高效网络挂载(linux网络挂载)
- 如何在Linux中配置NFS(nfs配置linux)
- Linux内核网卡驱动技术精准控制网络性能(linux内核 网卡驱动)
- 自动化Linux:将智能管理带入系统部署(aauto linux)
- Linux C高级编程:掌握技术,实现卓越(linux c 高级编程)
- 快乐Linux之旅:学习笔记(linux学习笔记)
- Linux 内核:强大无比的功能实现(linux 内核 功能)