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.

Steps to check for persistence with cron and systemctl in Linux:

  1. 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.*.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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
  7. 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/.

  8. 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.

  9. 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.

  10. 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.

  11. 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 --