Persistence after an intrusion often relies on scheduled execution or boot-time autostart so malicious code returns after reboots and logouts. Cron jobs and systemd units are common persistence locations because they blend into routine automation and maintenance.
Cron executes non-interactive commands from per-user crontabs and system-wide schedules such as /etc/crontab, /etc/cron.d, and the /etc/cron.* directories. Systemd starts enabled services at boot and can also trigger services via timer units, where the timer defines the schedule and the service defines the executed command.
Legitimate systems contain many scheduled tasks, so prioritize unknown names, newly added files under /etc/systemd/system, scripts in writable locations (/tmp, /var/tmp, home directories), and commands that launch interpreters or retrieve content over the network. Full enumeration typically requires root access, and timestamps can be misleading during incident response if system time changed or logs rotated.
Related: How to investigate a Linux intrusion
Related: How to list cron jobs in Linux
Steps to check for persistence with cron and systemctl in Linux:
- List the root user's crontab entries.
$ sudo crontab -l # m h dom mon dow command 0 5 * * * /usr/local/bin/backup.sh 15 * * * * /usr/local/bin/rotate-logs.sh
A missing root crontab is common and does not rule out system-wide jobs under /etc/cron.d or /etc/cron.*.
- List the target account's crontab entries.
$ sudo crontab -l -u alice # m h dom mon dow command @reboot /home/alice/.local/bin/check-updates.sh
Replace alice with the target account name and flag jobs using @reboot or executing from hidden or temporary paths.
- Review system cron directories for unexpected or recently changed scripts.
$ sudo ls -l /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly /etc/cron.d: total 8 -rw-r--r-- 1 root root 202 Apr 8 2024 e2scrub_all -rw-r--r-- 1 root root 396 Jan 9 2024 sysstat /etc/cron.daily: total 16 -rwxr-xr-x 1 root root 1478 Mar 22 2024 apt-compat -rwxr-xr-x 1 root root 123 Feb 5 2024 dpkg -rwxr-xr-x 1 root root 377 Apr 8 2024 logrotate -rwxr-xr-x 1 root root 518 Jan 9 2024 sysstat /etc/cron.hourly: total 0 /etc/cron.monthly: total 0 /etc/cron.weekly: total 0
System-wide schedules may also be defined in /etc/crontab and /etc/anacrontab if present.
- Search cron configuration for common persistence indicators.
$ sudo grep -R --line-number --extended-regexp --ignore-case '(curl|wget|base64|/dev/shm|/tmp|\.cache)' /etc/crontab /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly
No output indicates no matches for the selected patterns.
- List all systemd timers with the services they activate.
$ systemctl list-timers --all --no-pager | head -n 8 NEXT LEFT LAST PASSED UNIT ACTIVATES Tue 2026-01-13 22:33:14 UTC 6min Mon 2026-01-12 22:35:07 UTC 23h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service - - - - logrotate.timer logrotate.service 2 timers listed.
The ACTIVATES column often points directly at the persistence mechanism.
- List timer unit files to identify timers enabled at boot.
$ systemctl list-unit-files --type=timer --no-pager | head -n 8 UNIT FILE STATE PRESET apt-daily-upgrade.timer disabled enabled apt-daily.timer disabled enabled dpkg-db-backup.timer disabled enabled e2scrub_all.timer disabled enabled fstrim.timer disabled enabled logrotate.timer enabled enabled motd-news.timer disabled enabled
- List enabled systemd services to spot unexpected autostart units.
$ systemctl list-unit-files --type=service --state=enabled --no-pager | head -n 8 UNIT FILE STATE PRESET cron.service enabled enabled demo-startup.service enabled enabled dmesg.service enabled enabled firewalld.service enabled enabled rsyslog.service enabled enabled smartmontools.service enabled enabled ssh.service enabled enabled
Services enabled for autostart are commonly symlinked under /etc/systemd/system/*.wants/.
- Inspect a suspicious timer-activated service unit to identify its file path and ExecStart command.
$ systemctl cat logrotate.service # /usr/lib/systemd/system/logrotate.service [Unit] Description=Rotate log files Documentation=man:logrotate(8) man:logrotate.conf(5) RequiresMountsFor=/var/log ConditionACPower=true [Service] Type=oneshot ExecStart=/usr/sbin/logrotate /etc/logrotate.conf # performance options Nice=19 IOSchedulingClass=best-effort IOSchedulingPriority=7 # hardening options # details: https://www.freedesktop.org/software/systemd/man/systemd.exec.html # no ProtectHome for userdir logs # no PrivateNetwork for mail deliviery # no NoNewPrivileges for third party rotate scripts # no RestrictSUIDSGID for creating setgid directories LockPersonality=true MemoryDenyWriteExecute=true PrivateDevices=true PrivateTmp=true ProtectClock=true ProtectControlGroups=true ProtectHostname=true ProtectKernelLogs=true ProtectKernelModules=true ProtectKernelTunables=true ProtectSystem=full RestrictNamespaces=true RestrictRealtime=true
Stopping or disabling unknown units can break updates, monitoring, and backups; capture evidence and validate ownership before making changes.
- Check whether the target account has linger enabled for user services.
$ sudo loginctl show-user alice -p Linger Failed to get user: User ID 1005 is not logged in or lingering
Linger=yes allows per-user systemd units to run without an interactive login.
- Search for per-user systemd unit files under home directories.
$ sudo find /home -maxdepth 6 -type f \( -path '*/.config/systemd/user/*.service' -o -path '*/.config/systemd/user/*.timer' \) -print /home/bob/.config/systemd/user/ssh-agent.service
User unit files commonly live under /home/*/.config/systemd/user/ and may be paired as .timer + .service.
- Review recent log entries for a suspicious unit to confirm execution details.
$ sudo journalctl -u logrotate.service --since '24 hours ago' --no-pager | head -n 6 -- No entries --
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
