Quick answer

LinPEAS enumerates systemd services and timers, prints the systemd PATH, and checks unit-file permissions. Writable unit files and relative-path ExecStart entries are the findings that matter, because they let a low-privilege user change what root runs. All testing below assumes an authorised lab or engagement.

Where it appears in the output#

systemd checks are in the procs_crons_timers_srvcs_sockets section, alongside services, sockets and D-Bus. LinPEAS lists units, shows timer schedules, dumps the PATH systemd uses to resolve relative ExecStart paths, and flags unit files and drop-ins that are writable by the current user.

How to read a systemd finding#

  • A writable service/timer file is high priority — you control what root executes the next time the unit runs.
  • A relative ExecStart (no leading /) can be hijacked if any systemd PATH entry is writable — same idea as cron PATH hijack.
  • Timers are the modern equivalent of cron; treat them exactly the same way — check what they run, as whom, and whether you can write it.
  • Drop-in overrides in /etc/systemd/system/*.d/ are easy to miss; LinPEAS checks them, and so should you.

Reproduce the checks manually#

Reproduce the systemd enumeration
systemctl list-units --type=service --all 2>/dev/null
systemctl list-timers --all 2>/dev/null
systemctl cat backup.service 2>/dev/null      # resolved unit, incl. drop-ins
find /etc/systemd/ /lib/systemd/ /run/systemd/ -name '*.service' -writable 2>/dev/null
find /etc/systemd/system/*.d -writable 2>/dev/null  # writable drop-ins

From a writable unit to a tested technique (authorised lab)#

In a lab with a root-run service whose unit file you can modify, the proof follows the cron pattern — make the unit do something observable:

  1. 1

  2. 2

  3. 3

  4. 4

Authorised use only

Only on systems you are explicitly authorised to test. Editing service units changes what the system runs as root — on any other machine that is unauthorised access.

How to fix systemd findings (defensive)#

  • Unit files and drop-in directories must be root-owned and non-writable (644 files, 755 dirs).
  • Use absolute paths in ExecStart; never rely on PATH resolution.
  • Set User= explicitly — services that do not need root should not run as root.
  • Harden units with NoNewPrivileges=true, ProtectSystem=strict and ReadWritePaths= where the software allows.
  • Audit timers like cron jobs: what runs, as whom, on what schedule.
  • Re-run LinPEAS after hardening to confirm the findings are gone.

User units vs system units#

systemd runs two kinds of units, and the distinction matters for privilege analysis:

System unitsUser units
Location/etc/systemd/system/, /lib/systemd/system/~/.config/systemd/user/
Managed bysystemctl (root)systemctl --user (the user)
Runs asUser= or root by defaultThe owning user
Escalation valueHigh — a writable system unit runs as rootLow — already your privilege level
LinPEAS focusWritable system units, timers, drop-insListed for completeness

When LinPEAS flags a writable unit, check which kind it is before getting excited — only system units buy you privilege.

Sockets and D-Bus: the quieter surfaces#

LinPEAS also enumerates sockets and D-Bus services in this section. Two things to look for:

  • Writable socket units — a service activated by a socket you can trigger runs on your schedule, like a timer you control.
  • Exposed D-Bus services — system-bus services with loose policies can be invoked by unprivileged users to perform privileged actions; LinPEAS lists them, you audit the policy.
  • Both are rarer than cron/timer findings but higher-value when present, because defenders check them less often.

Auditing timers like cron#

Treat every timer with the same routine you use for cron jobs:

  • List them: systemctl list-timers --all — note schedule, unit and user.
  • Resolve each timer to its service: systemctl cat <name>.timer, then systemctl cat <name>.service.
  • Check writability of the .timer, the .service and any .d/ drop-ins.
  • Read ExecStart: absolute path? Which user? What does the binary do?
  • Check the timer's PATH handling the same way you check cron PATH.
  • Fix like cron: root-owned, non-writable, absolute paths, explicit User=.

Masked and failed units are signals too#

LinPEAS lists unit states — do not skip the odd ones: a masked unit is deliberately disabled (usually fine, note why), while a failed unit may indicate a crashed security control (firewall, audit daemon) or a half-removed service still referenced by a timer. Failed security-relevant units deserve the same attention as writable ones.

Related: systemd as an escalation surface, PATH risks, cron findings.

Sources & references

  1. linPEAS README
  2. PEASS-ng release — reviewed 20260908-dffb9496
  3. HackTricks: Linux privilege escalation