Bash Exported-Function Path Backdoor

In Bash versions before 4.2-048, the shell accepts function definitions whose names contain slashes — including names that are byte-for-byte absolute paths to executables. Combined with export -f, this lets an unprivileged user plant a shell function in the environment that a privileged process’s child shell will run instead of the real binary at that path. 1

The technique

function /path/to/executable { /bin/bash -p; }
export -f /path/to/executable

When a SUID/SGID program (or any privileged process) later relies on the current shell to invoke /path/to/executable — via system(), popen(), or a child script — the exported function shadows the real command and runs with the caller’s effective privileges. -p preserves the elevated euid into the interactive shell (see suid-shell-executable).

Why it worked

Two Bash behaviors intersect:

  1. Functions could be named like paths. POSIX requires function names to be “name”-tokens (no slashes), but Bash accepted them anyway. A privileged helper calling /usr/bin/foo would resolve the function /usr/bin/foo before ever consulting the filesystem. 2
  2. Exported functions ride the environment. export -f serializes the function into an environment variable, so any child Bash inherits it — no write access to PATH directories needed, unlike the relative-path variant in suid-shell-executable. 3

Bash 4.2-048 (2010) tightened function-name validation, and the later Shellshock-era changes (2014) further restricted how exported functions are imported into privileged shells — functions are no longer inherited at all when euid ≠ ruid (the same startup sanitization that neutralized the PS4 trick). 4

Defensive lessons

  • SUID binaries should never call out through a shell; use absolute paths with direct exec*() calls. 5
  • Sanitizing inherited shell state at privilege boundaries is Bash’s job now, but the broader pattern — the environment is untrusted input to a privileged process — is the same one that drives LD_PRELOAD/LD_LIBRARY_PATH sanitization (see ld-preload-trick) and sudo’s env_reset default.

Sources

Related: bash-ps4-prompt-exploit, suid-shell-executable, ld-preload-trick, unix-permissions

Footnotes

  1. Juggernaut-Sec — SUID/SGID Linux Privilege Escalation Part 2

  2. bash(1) — Linux manual page

  3. bash(1) — Linux manual page

  4. bash(1) — Linux manual page

  5. Juggernaut-Sec — SUID/SGID Linux Privilege Escalation Part 2