跳转至

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 系统的电视机/机顶盒等。

漏洞原理

漏洞利用

PoCs

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
创建日期: November 17, 2022