Systemd Unit and Timer Privilege Escalation
Systemd service and timer units define what runs, when, and as which user. Writable unit files, drop-in directories, EnvironmentFile paths, executable scripts, and working directories are all exploitable when a service runs as root. Timers are cron replacements and follow the same abuse patterns.
Prerequisites Check
List active timers — these are scheduled execution paths worth targeting:
List all running services and their users:
Find writable unit files across all systemd directories:
Units in /etc/systemd/system/ override system defaults and are the most common target. Units in /lib/systemd/system/ are package-managed but occasionally writable.
Inspect a Target Unit
Before exploiting, read the full resolved unit configuration including inherited settings:
systemctl cat shows the active file. systemctl show shows all resolved values including defaults. Key fields to identify attack surface:
ExecStart=— main execution pathExecStartPre=/ExecStartPost=— pre/post hooksExecReload=— reload hook, triggered bysystemctl reloadWorkingDirectory=— if writable, relative paths in the script are exploitableEnvironmentFile=— if writable, inject environment variablesUser=— confirms if it runs as root
Writable Service File — Direct Modification
If you can write to the .service file directly:
Replace or append an ExecStart:
/etc/systemd/system/backup.service
[Unit]
Description=Backup Service
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'cp /bin/bash /tmp/.rootbash && chmod u+s /tmp/.rootbash'
User=root
[Install]
WantedBy=multi-user.target
If systemctl daemon-reload requires privilege you do not have, wait for the service to restart naturally (reboot, scheduled trigger) or check if the existing ExecStart path is writable instead.
Writable Drop-in Directory
Drop-in files override specific settings of the parent unit. If a .service.d/ directory is writable:
Create an override that replaces the ExecStart. The empty ExecStart= line clears the original before redefining:
Writable ExecStart Script
The most common scenario — the unit file is root-owned but the script it calls is writable:
Wait for the service to run next (check with systemctl status backup.service for the last run time and schedule), or trigger it if you have permission:
ExecStartPre and ExecStartPost
Pre and post hooks run as the same user as the main service. If these paths are writable they are equivalent to ExecStart:
Also check ExecReload — triggered by systemctl reload, which may be permitted for your user even if restart is not.
Writable WorkingDirectory
If WorkingDirectory is set and writable, any relative path execution in the service script is exploitable:
If writable and the service calls ./run.sh or similar relative path:
See https://hackindex.io/platforms/linux/privilege-escalation/writable-path-hijacking for the general PATH hijacking technique.
Writable EnvironmentFile
If a service loads environment variables from a file and that file is writable, inject a PATH entry or other variables the service script uses:
Then plant your malicious binary in /tmp with the same name as an unqualified command the service calls.
Timers — Scheduled Execution
Timers trigger services on a schedule. Target the .timer file to control timing, the associated .service to control what runs. List all timers with next run time:
Check the associated service for each timer:
Apply any of the above techniques to the associated .service file. If the .timer file itself is writable, you can change the schedule to fire immediately:
/etc/systemd/system/logrotate.timer
[Unit]
Description=Trigger immediately
[Timer]
OnBootSec=5
OnUnitActiveSec=30
[Install]
WantedBy=timers.target
For cron-based scheduled execution abuse see https://hackindex.io/platforms/linux/privilege-escalation/cron-job-privilege-escalation.
systemctl edit (if Permitted via sudo/polkit)
Some systems allow non-root users to edit units via sudo or Polkit. If sudo -l shows systemctl:
This opens a drop-in editor automatically. Add:
[Service]
ExecStart=
ExecStart=/bin/bash -c 'cp /bin/bash /tmp/.rootbash && chmod u+s /tmp/.rootbash'
Save and exit. The drop-in is written to /etc/systemd/system/backup.service.d/override.conf automatically.
Check sudo permissions for systemctl specifically at https://hackindex.io/platforms/linux/privilege-escalation/sudo-misconfiguration.
References
-
systemd.service manualman7.org/linux/man-pages/man5/systemd.service.5.html (opens in new tab)
ExecStart and security behavior
-
systemd.timer manualman7.org/linux/man-pages/man5/systemd.timer.5.html (opens in new tab)
Timer scheduling syntax
-
systemd.unit Manualwww.freedesktop.org/software/systemd/man/systemd.unit.html (opens in new tab)
Drop-in directory behavior and override precedence.
Was this helpful?
Your feedback helps improve this page.