Exploiting the Cron Jobs Misconfigurations – Part 1
Get practical knowledge on how to exploit cron job basic misconfiguration to get a privileged shell and execute commands on behalf of the root user.
If you are coming from a Windows background, cron jobs are the same as scheduled tasks. It is a utility for POSIX OS to configure and execute scheduled tasks on behalf of the user. If you are new to cron jobs or want a refresher on the basics of it, I have already explained it here. Read the post, and come back.
In this post, I will mainly focus on the infosec point of view and walk you through few labs discussing the misconfigurations left in the system. Here is the list of labs I will be discussing
- Cron Jobs Gone Wild
- Cron Jobs Gone Wild II
- The Golden Logs
- Symlinks Get Me Worried!
- Not all PATHs are Secure
In this post I will be discussing the first three labs, the other two are discussed in another part – here
LAB: Cron Jobs Gone Wild
Starting off looking for suid binaries and couldn't find any, but the current user has permissions to manage the cron service. This means you can either start/stop/restart or check the status of the service. In this case, cron service is already running
The current user has no cron job configured in their crontab and the global crontab file doesn't contain any juicy information.
On checking /tmp/ directory contents, I found that there is monitor.tar.gz which is being updated every minute. Since there is no other user, so it must be unattended action via some job
On extracting the archive, I found that there are 5 files with names 1 - 5. Let's check what's the other path of file 1, to know from where exactly these are being archived
The directory /var/log/monitor contains all the files and the directory is world-writable. This means you can modify the files. But that is not the fun part.
You will realize that creating any file in the directory will be archived to the /tmp/monitor.tar.gz
So based on the above image, we can reverse engineer that the cron job could be doing following
cd /var/log/monitor && tar -cf /tmp/monitor.tar.gz *
Using *
is not a bad idea but what your shell does is expands * into files and folders in the current directory. Take a look in the following example where I have 5 files and on doing ls *, shell is sending all the files names to execve syscall
$ ls -l
total 0
-rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file1
-rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file2
-rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file3
-rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file4
-rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file5
$ strace -e execve ls *
execve("/usr/bin/ls", ["ls", "file1", "file2", "file3", "file4", "file5"], 0x7fffbe829118 /* 91 vars */) = 0
file1 file2 file3 file4 file5
+++ exited with 0 +++
Now think of a situation when I have a file with names exactly as of the argument passed to ls command. In the case of the -li
flags, it will print a long description and with file inode number.
$ touch -- "-li"
$ ls -l
total 0
-rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file1
-rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file2
-rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file3
-rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file4
-rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file5
-rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:49 -li
This time when you will do ls *, it is getting the ls -li
flag passed in, due to expanding glob pattern feature in the shell.
$ ls *
6966 0 -rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file1
6967 0 -rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file2
6968 0 -rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file3
6969 0 -rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file4
6970 0 -rw-r--r-- 1 terabyte terabyte 0 Aug 12 02:47 file5
We will use the above information to execute the command using tar. If you are new to tar, you can actually execute the command via tar using --checkpoint and --checkpoint-action parameters. You can also get this exploitation information from the GitHub repository https://github.com/cyberheartmi9/PayloadsAllTheThings/tree/master/Tar commands execution
You can either use netcat to get a reverse shell with root shell or set suid on /bin/bash and escalate privileges using -p flag. In this case, I have used the second approach to make things simpler.
LAB: Cron Jobs Gone Wild II
On checking sudo privileges, I found that users can manage cron job services and there is a file named message owned by the user and group root.
I found that there is another file in the /tmp/ directory with the same name and a message "Hey!! you are not root :("
I used the grep command to recursively search in the possible directory for that files containing "/tmp/message" in them. Luckily I found a file and also it is world-writable. So in this case, you can write your malicious code into this file and take over the system
I will stick to adding a suid bit on the bash program.
chmod +s /bin/bash
After another hit, you can see /bin/bash binary has SUID bit enabled. On running command /bin/bash -ip
, you will get a privileged interactive shell
LAB: The Golden Logs
On checking sudo privileges, I found that there are two services running. The postfix service is basically an SMTP server used with cron jobs to send the status of execution. Cron jobs can also be configured to send error messages on the mail
In this case, both the services are running.
The base directory of all the emails is stored in /var/mail/[username]. Here the contents of emails of root users are world-readable, this could be a treasure for us.
As expected, there is information of command being failed (/bin/sh /opt/exec.sh) and frequency of execution is 1 min, see the date in yellow marker
The misconfiguration, in this case, is that the /opt/
directory is world-writable. In this, you can create a exec.sh
file and add malicious content to get the root shell.
Here I am setting SUID bit on /bin/bash to get a privileged shell using the bash -p
command.
chmod u+s /bin/bash
On the next execution, the cron job will run /opt/exec.sh script and set SUID bit on the target file.