CoursesAdvanced Linux securityPersistence & rootkits

Where attackers persist

cron, systemd, SSH keys, shell profiles.

Advanced14 min · lesson 6 of 17

Once an attacker has access, their next priority is keeping it — persistence, so a reboot, a patch, or a killed process does not evict them. Linux offers many places to hook automatic execution, and an attacker only needs one; a defender must know them all. The good news is that most persistence lives in a finite, well-known set of locations, so knowing the map lets you audit for and detect the vast majority of it. The classics are scheduled tasks, service definitions, login scripts, and authorized keys.

Where Linux persistence hides
scheduled & service execution
cron / cron.d / crontabs
runs on a schedule
systemd services & timers
runs at boot / interval
login & access hooks
~/.ssh/authorized_keys
a planted key = a login
.bashrc / .profile / /etc/profile.d
runs on shell start
new users / sudoers entries
a fresh way in
An attacker needs one; you must watch them all. Baseline each, and alert on additions — they rarely change legitimately.

Scheduled tasks and services

The most common persistence is a scheduled job or a service that re-launches the attacker’s payload. Cron entries in /etc/crontab, /etc/cron.d/, and per-user crontabs; systemd service and timer units, especially in user or unusual directories — each will faithfully run the attacker’s code on schedule or at boot. Because legitimate cron jobs and services also live here, the detection is baseline-and-diff: a new unit or cron entry, particularly one pointing at /tmp, a hidden path, or an odd binary, is the signal.

terminal
# enumerate scheduled/service persistence — baseline these and alert on additions
$ cat /etc/crontab; ls -la /etc/cron.d/ /etc/cron.*/
$ for u in $(cut -f1 -d: /etc/passwd); do crontab -l -u "$u" 2>/dev/null; done
$ systemctl list-timers --all
$ systemctl list-unit-files --type=service | grep enabled # diff against known-good

Login hooks and keys

The other big family runs when someone (or something) logs in. A public key appended to ~/.ssh/authorized_keys is a silent, password-less backdoor. Commands added to shell startup files (.bashrc, .profile, /etc/profile.d/) run every time a shell opens. A new user account, or a fresh sudoers entry, is a straightforward "add my own way in." These are high-value to watch precisely because they are how the attacker guarantees return access — and because on a stable host, authorized_keys and shell profiles change rarely.

terminal
# the backdoor hunt — unexpected keys, new accounts, tampered startup files
$ find /home /root -name authorized_keys -exec ls -la {} + 2>/dev/null # unknown keys?
$ awk -F: '$3>=1000{print $1,$3}' /etc/passwd # accounts — any you did not create?
$ ls -la /etc/profile.d/ ~/.bashrc ~/.profile # shell hooks — any new lines?
Persistence is your best late-detection chance
You might miss the initial break-in, but persistence is durable by design — it has to survive on the system, which means it leaves an artifact you can find. Baseline every persistence location (cron, timers, services, authorized_keys, startup files, accounts, sudoers), diff them on a schedule, and treat any addition as an incident lead. An attacker who cleaned up their entry but left a backdoor cron job has handed you the thread that unravels the whole intrusion.