A recent vulnerability, CVE-2014-6271, in how Bash interprets environment variables was disclosed. The exploit relies on Bash parsing some environment variable declarations as function definitions, but then continuing to execute code following the definition:
$ x='() { echo i do nothing; }; echo vulnerable' bash -c ':' vulnerable
But I don't get it. There's nothing I've been able to find in the Bash manual about interpreting environment variables as functions at all (except for inheriting functions, which is different). Indeed, a proper named function definition is just treated as a value:
$ x='y() { :; }' bash -c 'echo $x' y() { :; }
But a corrupt one prints nothing:
$ x='() { :; }' bash -c 'echo $x' $ # Nothing but newline
The corrupt function is unnamed, and so I can't just call it. Is this vulnerability a pure implementation bug, or is there an intended feature here, that I just can't see?
Per Barmar's comment, I hypothesized the name of the function was the parameter name:
$ n='() { echo wat; }' bash -c 'n' wat
Which I could swear I tried before, but I guess I didn't try hard enough. It's repeatable now. Here's a little more testing:
$ env n='() { echo wat; }; echo vuln' bash -c 'n' vuln wat $ env n='() { echo wat; }; echo $1' bash -c 'n 2' 3 -- 4 wat
…so apparently the args are not set at the time the exploit executes.
Anyway, the basic answer to my question is, yes, this is how Bash implements inherited functions.
The flaw allows an attacker to remotely attach a malicious executable to a variable that is executed when Bash is invoked. In most of the examples on the Internet right now, attackers are remotely attacking web servers hosting CGI scripts that have been written in bash.
The correct answer is CGI (Common Gateway Interface). "The most common being web servers using CGI environment.”
The Bash Bug vulnerability (CVE-2014-6271) A new critical vulnerability, remotely exploitable, dubbed “Bash Bug”, is threatening billions of machines all over the world. The vulnerability was discovered by the security researcher Stephane Chazelas at Akamai firm.
This seems like an implementation bug.
Apparently, the way exported functions work in bash
is that they use specially-formatted environment variables. If you export a function:
f() { ... }
it defines an environment variable like:
f='() { ... }'
What's probably happening is that when the new shell sees an environment variable whose value begins with ()
, it prepends the variable name and executes the resulting string. The bug is that this includes executing anything after the function definition as well.
The fix described is apparently to parse the result to see if it's a valid function definition. If not, it prints the warning about the invalid function definition attempt.
This article confirms my explanation of the cause of the bug. It also goes into a little more detail about how the fix resolves it: not only do they parse the values more carefully, but variables that are used to pass exported functions follow a special naming convention. This naming convention is different from that used for the environment variables created for CGI scripts, so an HTTP client should never be able to get its foot into this door.
The following:
x='() { echo I do nothing; }; echo vulnerable' bash -c 'typeset -f'
prints
vulnerable x () { echo I do nothing } declare -fx x
seems, than Bash, after having parsed the x=...
, discovered it as a function, exported it, saw the declare -fx x
and allowed the execution of the command after the declaration.
echo vulnerable
x='() { x; }; echo vulnerable' bash -c 'typeset -f'
prints:
vulnerable x () { echo I do nothing }
and running the x
x='() { x; }; echo Vulnerable' bash -c 'x'
prints
Vulnerable Segmentation fault: 11
segfaults - infinite recursive calls
It doesn't overrides already defined function
$ x() { echo Something; } $ declare -fx x $ x='() { x; }; echo Vulnerable' bash -c 'typeset -f'
prints:
x () { echo Something } declare -fx x
e.g. the x remains the previously (correctly) defined function.
For the Bash 4.3.25(1)-release
the vulnerability is closed, so
x='() { echo I do nothing; }; echo Vulnerable' bash -c ':'
prints
bash: warning: x: ignoring function definition attempt bash: error importing function definition for `x'
but - what is strange (at least for me)
x='() { x; };' bash -c 'typeset -f'
STILL PRINTS
x () { x } declare -fx x
and the
x='() { x; };' bash -c 'x'
segmentation faults too, so it STILL accept the strange function definition...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With