Report

CVE-2014-7169 — Bash Shellshock secondary injection via function-name parser interpolation

87fd7785-08ae-4f3e-85ec-3c515de8ad49

CVE-2014-7169 is the incomplete-fix follow-up to the original Shellshock (CVE-2014-6271). Bash imports exported function definitions from environment variables in initialize_shell_variables (variables.c). After the first Shellshock patch added BASH_FUNC_%% prefix/suffix wrapping, the body-parsing side was sandboxed — but the function NAME side was still concatenated verbatim into the string fed to parse_and_execute. Because the legal_identifier(tname) check is gated behind posixly_correct == 0 || (and posixly_correct defaults to 0), the name is never validated in normal use. An attacker who controls an exported env var name (e.g. HTTP_* headers in CGI, sshd ForceCommand, DHCP option 114, qmail-style mail forwarders) can embed backticks, $(...), semicolons, or > redirection inside the name and gain RCE. Reachable via: main -> shell_initialize -> initialize_shell_variables -> parse_and_execute. 1. Briefing called out command-injection, "incomplete fix for Shellshock", and a call chain through initialize_shell_variables -> parse_and_execute. Searched the bash repo with grep -rn initialize_shell_variables -> variables.c:337. 2. Read variables.c lines 337-460. The function-import block (lines 368-417) builds temp_string = tname + ' ' + string and passes it to parse_and_execute with SEVAL_FUNCDEF|SEVAL_ONECMD. 3. Spotted line 394: if (absolute_program (tname) == 0 && (posixly_correct == 0 || legal_identifier (tname))). The posixly_correct == 0 || short-circuit means the legal_identifier check is skipped in the default (non-POSIX) shell mode — so tname can contain shell metacharacters. 4. Confirmed by reading the demo's cve_2014_7169_exploit.c which constructs an env var like "touch /tmp/PWN=() { :; }" — the backticks live in the variable NAME, not the body. 5. Cross-checked legal_identifier usage at lines 447, 2259, 3417, 3583 — confirmed it's the standard bash identifier validator, intentionally bypassed at 394. Useful grep patterns: STREQN.*"() {", parse_and_execute.*SEVAL_FUNCDEF, legal_identifier, posixly_correct.