dirty-cow-logo

A zero-day local privilege escalation vulnerability has been found in the Linux kernel that has existed since 2005, being called DirtyCow. This bug affects a large number of popular Linux distros as well as Android devices. By exploiting the DirtyCow vulnerability, any user can become root (admin) in less than 5 seconds. The vulnerability has existed since Linux kernel version 2.6.22+.

This bug is named as Dirty COW (CVE-2016-5195) is a privilege escalation vulnerability in the Linux Kernel. Exploitation of this bug does not leave any trace of anything abnormal happening to the logs. So you can not detect if someone has exploited this against your server.

About The DirtyCow Vulnerability

According to the project:

A race condition was found in the way the Linux kernel’s memory subsystem handled the copy-on-write (COW) breakage of private read-only memory mappings. An unprivileged local user could use this flaw to gain write access to otherwise read-only memory mappings and thus increase their privileges on the system.

Any local users can write to any file they can read, and present since at least Linux kernel version 2.6.22. Linus Torvalds explained:

This is an ancient bug that was actually attempted to be fixed once (badly) by me eleven years ago in commit 4ceb5db9757a (“Fix get_user_pages() race for write access”) but that was then undone due to problems on s390 by commit f33ea7f404e5 (“fix get_user_pages bug”).

In the meantime, the s390 situation has long been fixed, and we can now fix it by checking the pte_dirty() bit properly (and do it better). The s390 dirty bit was implemented in abf09bed3cce (“s390/mm: implement software dirty bits”) which made it into v3.9. Earlier kernels will have to look at the page state itself.

Also, the VM has become more scalable, and what used a purely theoretical race back then has become easier to trigger.

To fix it, we introduce a new internal FOLL_COW flag to mark the “yes, we already did a COW” rather than play racy games with FOLL_WRITE that is very fundamental, and then use the pte dirty flag to validate that the FOLL_COW flag is still valid.

The underlying bug was patched this week by the maintainers of the official Linux kernel. Downstream distributors are in the process of releasing updates that incorporate the fix.

Linux Distros Affected By DirtyCow:

A list of affected Linux distros (including VMs and containers that share the same kernel):

  • Red Hat Enterprise Linux 7.x
  • Red Hat Enterprise Linux 6.x
  • Red Hat Enterprise Linux 5.x
  • CentOS Linux 7.x
  • CentOS Linux 6.x
  • CentOS Linux 5.x
  • Debian Linux wheezy
  • Debian Linux jessie
  • Debian Linux stretch
  • Debian Linux sid
  • Ubuntu Linux precise (LTS 12.04)
  • Ubuntu Linux trusty
  • Ubuntu Linux xenial (LTS 16.04)
  • Ubuntu Linux yakkety
  • Ubuntu Linux vivid/ubuntu-core
  • SUSE Linux Enterprise 11 and 12

How do I fix DirtyCow CVE-2016-5195 on Linux?

Find Your Kernel Version

Type the commands as per your Linux distro. You need to reboot the box. Before you apply patch, note down your current kernel version:

$ uname -a
$ uname -mrs

Debian or Ubuntu Linux

$ sudo apt-get update && sudo apt-get upgrade && sudo apt-get dist-upgrade
$ sudo reboot

RHEL / CentOS Linux 5.x/6.x/7.x

$ sudo yum update
$ sudo reboot

RHEL / CentOS Linux 4.x

$ sudo up2date -u
$ sudo reboot

Suse Enterprise Linux or OpenSUSE Linux

# zypper patch
# reboot

Verification

You need to make sure your version number has changed:

$ uname -a
$ uname -r
$ uname -mrs

Determine You’re Vulnerable To DirtyCow

For RHEL/CentOS Linux, use the following script

$ wget https://access.redhat.com/sites/default/files/rh-cve-2016-5195_1.sh
$ bash rh-cve-2016-5195_1.sh

For all other distro try PoC (proof of concept exploit code)

Grab the PoC:

$ wget https://raw.githubusercontent.com/dirtycow/dirtycow.github.io/master/dirtyc0w.c

Run it as follows. First be root:

$ sudo -s
# echo this is not a test > foo

Run it as normal user:

$ gcc -lpthread dirtyc0w.c -o dirtyc0w
$ ./dirtyc0w foo m00000000000000000
mmap 56123000
madvise 0
procselfmem 1800000000
$ cat foo
m00000000000000000

References