Safeguard
Application Security•

Detecting and Mitigating Malicious Systemd Services (T1543.002)

Systemd unit files can run code at every boot as any user. See how .service files, symlinks and generators are abused, and how to audit them.

Safeguard Security Team
4 min read

Systemd Service abuse (MITRE ATT&CK T1543.002) is a persistence and privilege escalation technique on Linux. Systemd is the system and service manager on many distributions. It replaced older init systems such as SysVinit and Upstart while staying backward compatible.

If you manage Linux servers, unit files are among the first places to look after a suspected compromise. They are plain text, easy to read and easy to compare across machines.

How attackers use it

Systemd describes each service in a unit configuration file with a .service extension. By default, system level unit files are stored in the systemd/system directory under the root owned directories, and user level unit files are stored in the systemd/user directories under the user's home.

Inside a service file, several directives execute commands:

  • ExecStart, ExecStartPre and ExecStartPost run when the service is started manually with systemctl or at boot if the service is set to start automatically.
  • ExecReload runs when the service reloads or restarts.
  • ExecStop, ExecStopPre and ExecStopPost run when the service stops.

MITRE says adversaries have created new service files, changed the commands a directive runs and changed the user a service runs as. That last point can lead to privilege escalation based on the permissions of that user or group, since the User directive sets the account.

Two further tricks come from MITRE's description. Adversaries may place symbolic links in the unit directories, so systemd finds a payload wherever it lives on the filesystem. They may also use systemd generators, which are small executables that run during boot or configuration reloads to create or modify unit files dynamically. Generators convert non-native configurations into services, symlinks or drop-ins, which MITRE ties to Boot or Logon Initialization Scripts.

How to detect it

MITRE's strategy centers on file changes and the commands around them:

  • Creation or modification of .service unit files in system and user level directories.
  • Execution of systemctl or service, and drop-ins created through generators.
  • The ExecStart path, file entropy and symlink use.
  • Execution from /tmp, /dev/shm or unmounted volumes, which is a strong signal.

An auditd watch on the unit directories gives you file level visibility. In an auditd rules file:

-w /etc/systemd/system/ -p wa -k systemd_units
-w /usr/lib/systemd/system/ -p wa -k systemd_units

Then search the audit log for that key after changes:

ausearch -k systemd_units

Process creation logs help with the second half. A service whose binary runs out of a world-writable path stands out.

How to reduce the risk

MITRE lists four mitigations:

  1. Limit who can use systemctl. Give access to system utilities such as systemctl only to users who need it.
  2. Protect unit files. Restrict read and write access to unit files to the select privileged users who manage services.
  3. Treat unit changes as privileged. Creating and modifying unit files is generally reserved for administrators such as root and users with superuser privileges. Anything else is an anomaly.
  4. Limit software installation. Install only from trusted repositories, and be careful with orphaned packages.

Check your own environment

Read-only commands on Linux:

systemctl list-unit-files --state=enabled
systemctl cat suspicious.service
find /etc/systemd/system /usr/lib/systemd/system /lib/systemd/system -name '*.service' -mtime -14
find /etc/systemd/system -type l -ls
grep -rn 'ExecStart' /etc/systemd/system | grep -E '/tmp|/dev/shm|/var/tmp'

Replace suspicious.service with a unit from your own list. The symlink search is useful because MITRE calls out links as a way to hide the real payload location.

Then ask:

  1. Does each enabled unit belong to a package? Use your package manager to check ownership of the file.
  2. Does any ExecStart path sit in a temporary or user writable directory?
  3. Does any service run as a different user than its function needs?
  4. Are there generator directories with files you cannot explain?

Quick check

Why do symlinks in unit directories matter?

MITRE notes adversaries use symbolic links so systemd finds a payload regardless of where it sits on the filesystem, which can hide the real location from a quick directory listing.

Which unit file directive can cause privilege escalation?

The User directive, which sets the account the service runs as.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.