BACKGROUND

I recently came across several RHEL 6.x systems during a penetration test our team was performing for a customer. We had gained user level access on these machines and began enumerating privilege escalation possibilities. Given the somewhat recent discovery of the Dirty Cow vulnerability and what appears to be a manual patching requirement of RHEL systems, I decided to test some of the publicly available proof-of-concepts on the Dirty Cow github site.

In short, exploitation of the Dirty Cow vulnerability allows an unprivileged user to modify any file on the filesystem. To read more about the vulnerability itself, visit the Dirty Cow website. Many of the publicly available POCs achieve privilege escalation by overwriting files that are used for authentication. After testing several of the POCs on a test RHEL system, I found that the “/etc/passwd” overwrite technique of the PTRACE_POKEDATA family of exploits seemed to work best. This exploit overwrites the first line in “/etc/passwd” which defines the authentication details for the root user. I wasn’t able to get the /proc/self/mem technique to work due to what I believe was an issue related to the particular target operating system.

PROBLEM

While overwriting the first line of the “/etc/passwd” file was effective, the target systems were used by multiple users, implemented stringent selinux policies, and employed host intrustion software. In other words, running an exploit that modifies a critical system file like “/etc/passwd” presents a fairly significant chance of being detected. This change could be detected by the file modification itself, if another user tries to login as root before restoration, if file permissions are not correctly restored after restoration, or other authentication related issues.

With this in mind, I decided to begin searching for a different target file for the Dirty Cow “write to any file” exploit primitive. Unless my understanding is incorrect, our file write is limited to the modification of file contents and does not allow for appending data to a file. With our desire to go undetected, this means we need to find a file we can modify while also ensuring its original functionality. It would also be preferable to be able to schedule or trigger our privilege escalation.

SOLUTION

After some cursory research, we found a file called 0anacron in the /etc/cron.hourly/ folder. This particular folder runs cron jobs hourly with root privileges. A few google searches showed 0anacron to be a job installed by default on RedHat and Centos distributions. To ensure proper functionality of the original script, we decided to insert our custom code into the comment section of the script. To stay within the size limitation imposed by the length of the comment, the inserted code consists of a path to another script in the /tmp/ directory followed by a comment character. The filename is one randomly generated character. After running the exploit, the script will look like the following. #!/bin/bash

# Skip excecution unless the date has changed from the previous run

if test -r /var/spool/anacron/cron.daily; then

day=`cat /var/spool/anacron/cron.daily`

fi

if [ `date +%Y%m%d` = “$day” ]; then

exit 0;

fi /tmp/k;#xcecution unless AC powered

if test -x /usr/bin/on_ac_power; then

/usr/bin/on_ac_power &> /dev/null

if test $? -eq 1; then

exit 0

fi

fi

/usr/sbin/anacron -s

The finished exploit asks the user for the command to be written to the script that is generated in the /tmp/ directory. This command can be anything from a reverse shell callback to the setting of a suid binary. For our assessment, we decided to compile a binary that executes a setresuid shell with the code below, and use the /tmp/ root executed script to set the suid on the binary using the following commands: chown root /tmp/shell;chmod +s /tmp/shell

#define _GNU_SOURCE #include <stdlib.h> #include <unistd.h> void main(){ int euid = geteuid(); setresuid(euid,euid,euid); execl("/bin/bash", "/bin/bash", NULL); }