Writable Files & PATH Hijacking
A recurring privesc theme: root trusts something you can change. Sometimes it's a file root reads or runs; sometimes it's the name of a command root looks up through $PATH. Either way, if you control what root ends up executing, you control root.
Step 1: find what you can write
The single most productive enumeration command after SUID:
find / -writable -type f 2>/dev/null | grep -vE "/proc|/sys"
find / -writable -type d 2>/dev/null # writable directories too
Now ask of each hit: does anything running as root read or execute this? A writable file nobody privileged touches is harmless. A writable file in a root cron job, a systemd unit, a startup script, or a config a root service parses, that's your way up.
Writable files root trusts
Common high-value writable targets:
- A script run by root cron (you saw this in cron privesc).
- A systemd
.servicefile or itsExecStarttarget. If/etc/systemd/system/app.serviceis writable, pointExecStart=at your payload:
then it runs as root on the next restart or boot.[Service] ExecStart=/bin/bash -c 'cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash' - A config file a root daemon reads (some let you set a command, a plugin path, an include).
/etc/passwdor/etc/shadowif permissions are wrong (see weak permissions).
PATH hijacking
This one's subtle and very common. When a program runs a command by name (backup) instead of full path (/usr/bin/backup), the shell searches the directories in $PATH, in order, and runs the first match. Two things make it exploitable:
- A root process (a cron job, a SUID wrapper, a service) calls a command by bare name.
$PATHcontains a directory you can write to, listed before the real one.
backup (no full path)/home/analyst/bin/backup is found first → your code runs as rootPut a writable directory in front of PATH and you decide what "backup" means.
$ echo $PATH
/home/analyst/bin:/usr/bin:/bin # your dir is FIRST
# the root script runs 'backup' by name, so drop your own 'backup' first in PATH:
$ printf '#!/bin/bash\ncp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash\n' > /home/analyst/bin/backup
$ chmod +x /home/analyst/bin/backup
# ...root runs YOUR backup -> SUID root bash -> /tmp/rootbash -p
Even when PATH looks safe, a SUID binary that calls system("service …") or popen("id") without a full path is hijackable: you set PATH=/tmp:$PATH, drop a malicious service/id in /tmp, and run the SUID binary.
The fix (what you report)
Root-run scripts should be root-owned and non-writable by others, call every binary by absolute path, and set a clean, fixed PATH at the top. Never leave a world-writable directory early in root's PATH. Report the writable file (with its permissions) or the bare-name command call.
Common questions
"find / -writable printed hundreds of files. Which ones matter?"
Almost none of them on their own. A writable file is only a privesc if something running as root reads or runs it. Cross-reference your writable hits against root cron jobs, systemd units, and startup scripts, ignore the writable files in your own home directory and /tmp.
"How do I know if PATH hijacking will even work here?"
Two checks. Run echo $PATH, is a directory you can write to listed before /usr/bin? And does a root process call a command by bare name (backup) rather than full path (/usr/bin/backup)? You need both. If PATH is clean and root uses absolute paths, this vector is closed.
"My PATH looks safe (system dirs only). Is PATH hijacking off the table?"
Not always. A SUID binary that internally calls system("id") with a bare name is still hijackable, you prepend your own directory (PATH=/tmp:$PATH), drop a fake id there, and run the SUID program. The binary trusts PATH even if your login shell's PATH looked fine.
"Why edit ExecStart in a .service file instead of just running the service?"
Because ExecStart is the command systemd runs as root when the unit starts. If the unit file is writable, you point that line at your payload, then trigger a restart (or wait for boot) and root runs it for you. Same "root trusts something you can change" idea as cron.
Why this matters
These bugs need no exploit code, just find, echo, and an understanding of who runs what. A single writable service file or a sloppy $PATH is one of the most common real-world privescs, and one of the easiest to miss if you don't go looking.