BIPI
BIPI

Cron Job and Systemd Timer Privilege Escalation

Cybersecurity

Cron and systemd timers run as root on a schedule, and they are full of writable scripts, weak permissions, and PATH games. We cover how to find them and abuse them.

By Arjun Raghavan, Security & Systems Lead, BIPI · March 14, 2025 · 10 min read

#linux#cron#systemd#privesc#pspy

Scheduled tasks are a privesc factory

Cron jobs and systemd timers run as a chosen user, usually root, on a predictable schedule. If you can influence what they execute, you control what runs as root. The trick is finding the influence point.

Enumerating cron

  • ls -la /etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.weekly /etc/cron.monthly
  • cat /etc/crontab and per user crontabs in /var/spool/cron/crontabs
  • ls -la /var/spool/anacron for anacron jobs
  • Read scripts referenced in cron entries, especially those owned by other users
  • Check file permissions on each referenced script and its parent directories

Enumerating systemd timers

  • systemctl list-timers --all shows every timer and its next run
  • For each timer, systemctl cat timer.timer and the matching .service unit
  • Check ExecStart paths and the user the service runs as
  • ls -la on the binary or script, look for writable group or other

pspy is your friend

pspy by DominicBreuker watches /proc for new processes without needing root. Run pspy64 in a screen session for thirty minutes. You will see every cron and timer fire, every command they invoke, and every environment variable they pass.

Common abuse patterns

  1. Writable script referenced by a root cron, append a reverse shell line
  2. Wildcard in a cron command, drop a malicious file with a flag like name
  3. PATH set to /usr/local/bin:/usr/bin:/bin with a writable /usr/local/bin
  4. Cron invoking a binary without an absolute path, PATH hijack
  5. tar with a wildcard in a backup cron, classic --checkpoint-action exploit

Writable systemd unit files

  • ls -la /etc/systemd/system /lib/systemd/system /run/systemd/system
  • Any writable .service or .timer file is a direct path to root
  • Drop user units in ~/.config/systemd/user, then check if they run as a privileged user
  • Watch for unit files in non standard paths included via Alias or Wants

Race conditions on cron scripts

If a cron script is owned by root but lives in a directory writable by your user, you can delete and replace it just before the cron fires. Combine with inotifywait to time the swap perfectly.

Detection and hardening

  • File integrity monitoring on /etc/cron.* and /etc/systemd/system
  • auditd watch on /etc/crontab and /var/spool/cron
  • Falco rule on writes to cron and systemd paths by non root users
  • Set ProtectSystem=strict and NoNewPrivileges=yes in unit files
  • Use absolute paths in every scheduled command, never rely on PATH
If you find a cron and forget to also enumerate systemd timers, you have skipped half the modern Linux scheduling surface.

Operator habit

On every Linux box, run pspy in a screen session as soon as you have a shell. By the time you finish your other enumeration, you will have a log of every privileged process the box ran in the last half hour.

Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.