CVE-2016-5195 Dirty Cow¶
Description¶
The Dirty COW (CVE-2016-5195) vulnerability allows local users to gain root privileges on Linux systems.
低权限用户可以利用该漏洞写入对自身只读的内存页(包括可写文件系统上对该用户只读的文件)并提权至 root
该漏洞影响所有目前运行 Linux 系统的设备,包括但不限于运行 Linux 系统的服务器、Docker 容器服务、使用 Linux 操作系统的路由器、Android 手机/平板、搭载了 Android 系统的电视机/机顶盒等。
漏洞原理¶
- Dirty COW
- Dirty COW (CVE-2016-5195) - 漏洞详情
- 视频:Explaining Dirty COW local root exploit - CVE-2016-5195
漏洞利用¶
Table of PoCs¶
Note: if you experience crashes or locks take a look at this fix.
Link | Usage | Description | Family |
---|---|---|---|
dirtyc0w.c | ./dirtyc0w file content | Read-only write | /proc/self/mem |
cowroot.c | ./cowroot | SUID-based root | /proc/self/mem |
dirtycow-mem.c | ./dirtycow-mem | libc-based root | /proc/self/mem |
pokemon.c | ./d file content | Read-only write | PTRACE_POKEDATA |
dirtycow.cr | dirtycow --target --string --offset | Read-only write | /proc/self/mem |
dirtyc0w.c | ./dirtycow file content | Read-only write (Android) | /proc/self/mem |
dirtycow.rb | use exploit/linux/local/dirtycow and run | SUID-based root | /proc/self/mem |
0xdeadbeef.c | ./0xdeadbeef | vDSO-based root | PTRACE_POKEDATA |
naughtyc0w.c | ./c0w suid | SUID-based root | /proc/self/mem |
c0w.c | ./c0w | SUID-based root | PTRACE_POKEDATA |
dirty_pass[...].c | ./dirty_passwd_adjust_cow | /etc/passwd based root | /proc/self/mem |
mucow.c | ./mucow destination < payload.exe | Read-only write (multi page) | PTRACE_POKEDATA |
cowpy.c | r2pm -i dirtycow | Read-only write (radare2) | /proc/self/mem |
dirtycow.fasm | ./main | SUID-based root | /proc/self/mem |
dcow.cpp | ./dcow | /etc/passwd based root | /proc/self/mem |
dirtyc0w.go | go run dirtyc0w.go -f=file -c=content | Read-only write | /proc/self/mem |
dirty.c | ./dirty | /etc/passwd based root | PTRACE_POKEDATA |
List of PoCs¶
- Allows user to write on files meant to be read only. Link
- Gives the user root by overwriting
/usr/bin/passwd
or a suid binary. Link - Gives the user root by patching libc's getuid call and invoking
su
.Link - Allows user to write on files meant to be read only. Link
- Allows a user to write on files meant to be read only. Link
- Allows user to write on files meant to be read only (android). Link
- Metasploit module based on the
cowroot
PoC. Link - Gives the user root by patching the vDSO escapes containers/SELinux doesn't need suid. Link
- Gives the user root by injecting shellcode into a SUID file. Link
- Gives the user root by injecting shellcode into a SUID file using PTRACE_POKEDATA . Link
- Gives the user root by replacing /etc/passwd Link
- Allows user to write on files meant to be read only. Supports writing to multiple pages, not just the first Link
- Allows the user to write on files meant to be read only, implemented as a radare2 IO plugin. Link
- Gives the user root by injecting shellcode into a SUID file. implemented for amd64 in flatassembly. Link
- Gives the user root by replacing /etc/passwd Link
- Allows user to write on files meant to be read only. implemented for arm32/x86/amd64 in Golang faster than c implement. Link
- Generates a new password hash on the fly and modifies /etc/passwd automatically. Just run and pwn. Link
漏洞修复¶
检测您的系统是否存在脏牛漏洞,如果存在,建议您尽快升级内核版本。
免重启热修补¶
由于该漏洞位于 Linux 内核,发行版官方的内核更新只有在重启后才能生效。如果您的线上业务不能中断,可以采用下面这种基于 systemtap
的热修补方法,并在合适的时候更新系统内核。
systemtap 是一款内核调试、性能分析工具,其原理是插入新的内核模块并根据需要修改逻辑,实现功能。该工具同样可以被用于安全应急响应,在不重启系统的前提下修补安全漏洞或者提高利用难度。
针对 CVE-2016-5195 的 systemtap 热修补补丁最先出现在 Red Hat 公司 Bug 追踪系统的讨论区(出处),内容节选如下:
probe kernel.function("mem_write").call ? { $count = 0 }
probe syscall.ptrace { $request = 0xfff }
注意
该补丁仅适用于 64 位系统,且需要安装 systemtap 工具。 通过阻止写入 /proc/self/mem
来达到阻止上述利用代码的目的。该补丁有较为明显的副作用:无法调试程序,还可能导致 RHEL/CentOS 6 和 Ubuntu 14.04 上使用的 upstart 服务管理机制不能正常工作。
本文提供另一种热修补方式,代码如下:
probe kernel.function("sys_madvise") {
if ($behavior == 4) { $behavior = 0 }
}
Ubuntu系统前置步骤¶
# apt-get install gcc systemtap
# ddeb_filename=$(dpkg-query --show --showformat='${Package}-dbgsym_${Version}_${Architecture}.ddeb' linux-image-$(uname -r))
# wget http://ddebs.ubuntu.com/pool/main/l/linux/${ddeb_filename}
# dpkg -i ${ddeb_filename}
Debian系统前置步骤¶
由于 Debian 系统在同一包名下存在多个版本,需要从 snapshot 镜像下载或者自己编译得到调试信息,这里从略
RHEL/CentOS系统安装步骤¶
# yum install systemtap
现在需要安装与正在运行的内核版本相同的头文件和调试信息,主要是以下几个包:
1. `kernel-devel-$(uname -r)`
2. `kernel-debuginfo-common-$(arch)-$(uname -r)`
3. `kernel-debuginfo-$(uname -r)`
可以手工搜索相应的包名,下载 rpm 并安装(请尽量从官方源下载,使用错误的包可能导致内核崩溃)
测试systemtap安装成功:
# stap -e 'probe begin { print("hello world\n"); exit(); }'
hello world
执行热修补
# stap -Fge 'probe kernel.function("sys_madvise") { if ($behavior == 4) { $behavior = 0 }}'
Disconnecting from systemtap module.
To reconnect, type "staprun -A stap_9f8ce8307eb418da7c981b3223eec678_12644"
修补完成
# lsmod | grep stap
stap_9f8ce8307eb418da7c981b3223eec678_12644 81920 0
可以看到 systemtap 编译出的内核模块已经成功加载。
创建日期: November 17, 2022