On Linux, persistence is almost always a file in a known location: a cron entry, a systemd service or timer unit, an rc script, or a line in a shell profile. Unlike Windows, there is little registry-style indirection, so file-integrity watches on a short list of paths give very good coverage. The challenge is volume and attribution, particularly on hosts managed by configuration tools.
Signals at a Glance
| Signal | Where | ATT&CK |
|---|---|---|
| Write to /etc/crontab, /etc/cron.d/, /etc/cron.*/ or /var/spool/cron/ | auditd, FIM, EDR file events | T1053.003 |
| New .service or .timer file in /etc/systemd/system or ~/.config/systemd/user | auditd, FIM | T1543.002 |
| systemctl enable of a unit that was created minutes earlier | Process execution, journald | T1053.006 |
| Edit to /etc/rc.local, init.d scripts or /etc/profile.d/ | auditd, FIM | T1037.004 |
| Modification of ~/.bashrc, ~/.profile or ~/.bash_login by a non-user process | auditd, EDR | T1546.004 |
| Unit ExecStart or cron command pointing at /tmp, /dev/shm or a hidden directory | File content inspection | T1543.002 |
Watching the Persistence Paths
An auditd rule set that watches the standard locations is cheap and reliable. Tag each watch with a key so that your SIEM can route and enrich the events. Add the per-user paths through your configuration management, since auditd does not expand wildcards in watch paths:
# /etc/audit/rules.d/persistence.rules # cron -w /etc/crontab -p wa -k persist_cron -w /etc/cron.d/ -p wa -k persist_cron -w /etc/cron.hourly/ -p wa -k persist_cron -w /etc/cron.daily/ -p wa -k persist_cron -w /var/spool/cron/ -p wa -k persist_cron # systemd -w /etc/systemd/system/ -p wa -k persist_systemd -w /usr/lib/systemd/system/ -p wa -k persist_systemd -w /etc/systemd/user/ -p wa -k persist_systemd # rc and profile scripts -w /etc/rc.local -p wa -k persist_rc -w /etc/init.d/ -p wa -k persist_rc -w /etc/profile -p wa -k persist_profile -w /etc/profile.d/ -p wa -k persist_profile -w /etc/bash.bashrc -p wa -k persist_profile # tune/validate: expect package managers and config tools to write here; filter by auid and exe.
Auditd tells you that a path changed. To decide whether the change matters, inspect the content. The hunt below finds unit files and cron entries that execute from locations an administrator would not use, plus profile files that fetch and run remote content:
#!/bin/bash # Fleet hunt: persistence content that executes from unusual locations grep -RIlE 'Exec(Start|StartPre|StartPost)=.*(/tmp/|/dev/shm/|/var/tmp/|/\.[a-z0-9_.-]+/)' \ /etc/systemd/system /usr/lib/systemd/system /home/*/.config/systemd/user 2>/dev/null grep -RIE '(/tmp/|/dev/shm/|/var/tmp/|curl[^|]*\|\s*(ba)?sh|wget[^|]*\|\s*(ba)?sh|base64\s+-d)' \ /etc/crontab /etc/cron.d /var/spool/cron 2>/dev/null grep -IEn '(curl|wget).*(\||;).*(sh|bash)|nc -e|/dev/tcp/' \ /root/.bashrc /root/.profile /home/*/.bashrc /home/*/.profile /etc/profile.d/* 2>/dev/null find /etc/systemd/system /usr/lib/systemd/system -name '*.service' -newermt '-7 days' 2>/dev/null # tune/validate: review matches by hand first; build an allowlist of hashes from your golden image.
Attributing and Prioritising Changes
- Use the audit user (auid) and executable. A unit file written by
dpkg,rpmor a configuration management agent is routine; one written bybashorcurlfrom an SSH session is not. - Watch
systemctl enableandsystemctl daemon-reloadin process telemetry, and alert when they follow a file write from the same session. - Include user-level persistence. Systemd user units,
crontab -efor unprivileged users and shell profile edits need no root, so they matter on container hosts and developer machines. - Check timers. A
.timerunit paired with an unremarkable service name is a quiet alternative to cron and is often overlooked. - Immutable and read-only root filesystems, plus FIM on the listed paths, reduce this class of persistence to a short, reviewable change feed.
Use the SigmaHQ Linux persistence rules, Elastic’s Linux cron, systemd and shell-profile detections, Splunk ESCU content, MITRE CAR analytics, Atomic Red Team tests for T1053.003 and T1543.002, and the osquery crontab and systemd_units tables for inventory. Baseline your own environment, because configuration management tools write these paths constantly.
Build Detections That Fire
Mjolnir Security helps blue teams turn threat intelligence into high-fidelity detections across endpoint, network, identity and cloud telemetry.
- Detection Engineering We build and tune detections mapped to ATT&CK from your own telemetry.
- Threat Hunting as a Service Hypothesis-driven hunts for the behaviours on this page.
- 24/7 Incident Response Containment when a detection fires. Call +1 833 403 5875.
Stay ahead of emerging threats. Get notified when we publish new intelligence reports and advisories.
Subscribe to Alerts