This note documents detection patterns related to Systemd Service Persistence on Linux systems.
Direct Indicators
| Source | Grep Pattern / Artifact | Meaning | Forensic Value | Notes |
|---|---|---|---|---|
/etc/systemd/system/ | New .service file | Custom persistent service installed | Critical | Primary systemd persistence artifact. |
/lib/systemd/system/ | Modified unit file | Service tampering | Critical | May overwrite legitimate service definitions. |
| User systemd path | ~/.config/systemd/user/ | Per-user persistence | Critical | Often missed during triage. |
| Service file | ExecStart= | Executed command path | Critical | Highest-value persistence field. |
| Service file | /tmp, /dev/shm, hidden path | Suspicious execution target | Critical | Very high confidence malicious signal. |
| Service file | Restart=always | Persistence resilience | High | Common attacker durability pattern. |
| Shell history | systemctl enable | Persistence activation | Critical | Strong operator evidence. |
| Shell history | systemctl daemon-reload | Service registration | Critical | Typical service insertion step. |
| Shell history | systemctl start | Immediate persistence test | High | Confirms activation attempt. |
journalctl | service start records | Execution evidence | Critical | Primary runtime confirmation. |
auditd | write to service paths | Process attribution | Critical | Best attribution if enabled. |
| File timestamps | recent service creation | Timeline anchor | Critical | Correlates with intrusion window. |
| Service ownership anomaly | unexpected owner | High | Reveals attacker mistake. | |
| Symbolic link in wants target | enabled persistence link | Critical | Service auto-start confirmed. |
Indirect Indicators
| Indicator | What To Look For | Forensic Value | Notes |
|---|---|---|---|
| Service added after SSH or sudo | Stabilization after foothold | Critical | Common attacker progression. |
| Service name mimics legitimate daemon | Camouflage | Critical | Very common stealth pattern. |
| Service runs hidden script | Secondary payload | Critical | Often temp or hidden home path. |
| Service restarts repeatedly | Beacon durability | High | Common malicious persistence behavior. |
| User service under dormant account | Silent persistence | Critical | Often overlooked. |
| Service points to deleted file | Cleanup after insertion | High | Indicates incomplete cleanup. |
| Legitimate unit modified recently | Service hijack | Critical | Harder to spot than new file. |
| Service starts outbound connection | Callback persistence | Critical | Strong compromise signal. |
| Service plus cron or key persistence | Redundant persistence | Critical | Advanced operator behavior. |
| Daemon reload near intrusion timeline | Service registration event | High | Useful temporal clue. |
Common Tools
| Tool | Usage |
|---|---|
systemctl enable | Persist service across reboot. |
systemctl start | Immediate execution. |
systemctl daemon-reload | Register new service definition. |
| Direct file edit | Drop service file manually. |
ln -s | Manual enable through wants symlink. |
Relevant Artifacts
| Artifact | Path / Command | Forensic Value | Notes |
|---|---|---|---|
| System services | /etc/systemd/system/ | Critical | Primary persistence path. |
| Vendor services | /lib/systemd/system/ | Critical | Service hijack possibility. |
| User services | ~/.config/systemd/user/ | Critical | User persistence path. |
| Wants symlinks | multi-user.target.wants/ | Critical | Enablement truth. |
| Journald | journalctl | Critical | Runtime execution evidence. |
| Shell history | .bash_history, .zsh_history | Critical | Service creation commands. |
| Audit logs | /var/log/audit/audit.log | Critical | File write attribution. |
| Payload target | ExecStart referenced file | Critical | Actual executable under service. |
MITRE ATT&CK References
- T1543 Create or Modify System Process
- T1543.002 Systemd Service
- T1053 Scheduled Task or Job
Decision Tree
-
Is new or modified service present?
- Enumerate system and user service paths.
-
Is service expected?
- Validate naming, purpose, package ownership.
-
What does ExecStart launch?
- Inspect target file and arguments.
-
Is service enabled?
- Check wants symlink or enable state.
-
Has it executed?
- Review journal runtime records.
-
Pivot
- Service file → payload path.
- Payload path → timestamps and hashes.
- User → intrusion timeline.
-
Confirm persistence
- Unknown service + suspicious ExecStart + intrusion timing = malicious persistence.
Example Detection Templates
Grep
grep -R "ExecStart=" /etc/systemd/system /lib/systemd/system ~/.config/systemd/user 2>/dev/null
grep -R "/tmp\|/dev/shm\|bash\|python\|curl\|wget" /etc/systemd/system /lib/systemd/system ~/.config/systemd/user 2>/dev/null
grep -R "systemctl enable\|daemon-reload\|systemctl start" /home/*/.bash_history /root/.bash_history 2>/dev/null
Journalctl
journalctl | grep systemd
journalctl -u suspicious.service
File Inspection
find /etc/systemd/system /lib/systemd/system -type f -printf '%TY-%Tm-%Td %TT %p\n' 2>/dev/null | sort
find /etc/systemd/system -type l 2>/dev/null
Sigma
title: Linux Systemd Service Persistence
id: linux-systemd-service-persistence
status: experimental
description: Detects suspicious systemd service creation or execution indicators
logsource:
product: linux
detection:
selection_keywords:
message|contains:
- 'systemd'
- 'ExecStart'
- 'daemon-reload'
condition: selection_keywords
fields:
- message
- hostname
falsepositives:
- Legitimate service deployment
level: high
tags:
- attack.persistence
- attack.t1543.002
Mitigation & Hardening
| Control Area | Mitigation | Effectiveness | Notes |
|---|---|---|---|
| Service baseline | Inventory expected unit files | Critical | Unknown services should stand out. |
| File monitoring | Watch systemd paths | Critical | Strong invariant detection. |
| Least privilege | Restrict service creation rights | High | Limits persistence insertion. |
| Auditd | Monitor writes to service paths | High | Strong attribution. |
| Temp execution control | Block service execution from temp paths | Critical | Stops common abuse. |
| Journald retention | Preserve service logs | High | Needed for runtime proof. |
Fast Triage Checks
| Question | Command / Artifact | Why It Matters |
|---|---|---|
| Any new service files? | inspect systemd dirs | Immediate persistence check. |
| Is ExecStart suspicious? | inspect service content | Execution truth. |
| Is service enabled? | inspect wants symlinks | Persistence confirmation. |
| Has service run? | journalctl | Runtime proof. |
| Is payload still present? | inspect target path | Payload analysis. |
| Was service added post-login? | correlate timestamps | Intrusion chain. |
High Value Grep Strings
| Pattern | Why It Matters |
|---|---|
ExecStart= | Core execution field. |
Restart=always | Durability signal. |
/tmp | Suspicious path. |
/dev/shm | Stealth path. |
systemctl enable | Activation command. |
daemon-reload | Registration step. |
WantedBy= | Enablement context. |
Analyst Notes
| Scenario | Interpretation |
|---|---|
| Service name mimics legit daemon | Strong camouflage attempt. |
| ExecStart in temp path | High-confidence malicious persistence. |
| User-level service only | Stealth persistence under account context. |
| Service plus outbound callback | Active beacon persistence likely. |
| Modified legit service | Service hijack harder to spot. |
| Service + cron redundancy | Strong operator persistence discipline. |