Command Triggers

Finding commands that are / can be executed with elevated privileges

Automated (Cron Jobs)

Cron Jobs are a default way to execute commands or scripts in regular intervals. You can make scripts run every 2 minutes, every hour, every 3rd day of the month, etc. They execute commands as certain users, so if we as a low-privileged user can change some behavior of these commands to get us as shell as that other user, we escalate privileges.

Cron table files (crontabs) store the configuration for cron jobs. The system-wide crontab is located at /etc/crontab which is often readable by all users:

/etc/crontab
SHELL=/bin/sh
PATH=/home/user:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
# Custom
* * * * * root overwrite.sh
* * * * * root /usr/local/bin/compress.sh

Here the top 4 jobs are pretty standard. Using the run-parts command they just say to run the scripts inside /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly and /etc/cron.monthly. They also say exactly when it will run, indicated by the first 5 values. The /etc/cron.daily directory for example runs every day at 6:25 AM.

In the example above, there are also two overwrite.sh and compress.sh scripts, which run every minute (indicated by the * * * * *, here's a tool). These are often interesting because they run very often, allowing us lots of chances to mess with them.

Tip: Use the date command to see the exact current time. Cron jobs execute at the 0-second mark so you'll know exactly when your payload should have executed.

You can even use watch -n 1 date to get a date output that updates every second, so you can count down to exactly when it executes

These rules often trigger scripts, which are very valuable to read and understand when possible. More configurations like the $PATH variable are interesting to check, but most exploitation comes from the commands that are executed, and how you can influence them. For example, by overwriting the scripts directly with sufficient permissions, or writing malicious files that it uses.

Sudo

Using this command you get a list of commands you can execute as other users:

sudo -l

If you get any error message like these, it means you probably cannot use this technique for this user:

Sorry, user <username> may not run sudo on <machine>.

<username> is not in the sudoers file. This incident will be reported.

In the best-case scenario, you can run any command (even sudo /bin/bash) as root (without a password):

Matching Defaults entries:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User <username> may run the following commands:
    (ALL) NOPASSWD: ALL

Another more common example is that you can only execute a certain program or the NOPASSWD tag is not set meaning you do need to enter the current user's password:

User may run the following commands:
    (ALL : ALL) /usr/bin/find

$ sudo find
Password: 

Another common syntax to recognize is which other user you execute the command as, as this is not always root:

User may run the following commands:
    (administrator) /usr/bin/cat

$ sudo -u administrator cat

env_keep

Sometimes the program itself is not exploitable, but there is an env_keep option. This option allows you to keep environment variables while executing the program, that normally get cleared.

$ sudo -l
Matching Defaults entries for user on this host:
    env_reset, env_keep+=LD_PRELOAD, env_keep+=LD_LIBRARY_PATH

User user may run the following commands on this host:
    (root) NOPASSWD: /usr/sbin/apache2

Normally no environment variables are set at all (env_reset is doing this). All names added via env_keep+= can be set in your shell session, and will be kept when you run sudo. If it were !env_reset instead, all variables would be kept. This is even more exploitable as many ways exist to use environment variables for unintended behavior (see Environment Variables).

SetUID

Set User ID (SUID) binaries are programs that when executed by anyone, will perform actions with the permissions of the owner of the program. All programs are files, and the SUID bit on a program is just a permission like read/write/execute that you might be familiar with. The SUID bit can be seen as an s character where there would normally be an x for executable permissions:

$ ls -la /usr/bin/sudo
-rwsr-xr-x 2 root root 168136 Jan  5  2016 /usr/bin/sudo
   ^  ^       ^     ^
SUID  SGID   user group

When this s permission is set by the owner, it means that for anyone executing this program, it will be like the owner of the program ran it. If the file owner is root for example, then you would be executing the program as root. This sounds very dangerous because it is.

Note: The Set Group ID (SGID) bit is very similar. When executed by anyone, it just sets the permissions to those of the group owner of the file. The second name in the ls output is the group, so you can see what permissions you would be getting

As a defender, you need to be absolutely sure that the program that is executing cannot do things other users shouldn't be able to do, like reading files, writing files, or executing arbitrary commands. Programs like sudo in the example above are secured by asking for a password and checking permissions very carefully. But this is also why a vulnerability in sudo or any other SUID program is a big deal.

To find all files on the system having the SUID or SGID bit set, you can use a find command:

find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2>/dev/null

An important note is that executing these programs keeps the environment variables that you set. This opens up a whole load of new inputs the binary does something with. The $LD_PRELOAD & $LD_LIBRARY_PATH variables are filtered, but the $PATH variable is kept! If developers aren't careful to use absolute paths, this resolution can be overwritten by an attacker.

Note: Shell scripts do not use the SUID bit, these only matter on ELF executables. This was a decision made because SUID binaries should be as secure as possible (more info)

Last updated