With a bash release which has been patched for shellshock
$ bash --version
GNU bash, version 3.2.52(1)-release (x86_64-apple-darwin12)
Copyright (C) 2007 Free Software Foundation, Inc.
$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x'
this is a test
another similar exploit still works and has been assigned CVE-2014-7169
$ env X='() { (a)=>\' bash -c "echo date"; cat echo
bash: X: line 1: syntax error near unexpected token `='
bash: X: line 1: `'
bash: error importing function definition for `X'
Thu Sep 25 12:47:22 EDT 2014
$ ls echo
echo
Looking for a breakdown of this as well.
CVE-2014-7169 is a bug in bash's parser. Bash's parser uses a variable eol_ungetc_lookahead
to ungetc characters across lines. That variable wasn't being properly reset from the reset_parser
function, which is called e.g. on some syntax errors. Using that bug, it's possible to inject a character into the start of the next bash input line.
So the test code forces a syntax error, using either (a)=
or function a a
, adds the redirection character to prepend to the next line >
, and adds a line continuation \
, which leads to either version of the test code:
() { (a)=>\
() { function a a>\
When bash is executed, it processes variables from the environment, finds that variable X
is a exported function, and evaluates it to import the function. But the evaluation fails with a parse error, leaving the >
character in the eol_ungetc_lookahead
variable. Then, when parsing the command argument echo date
, it prepends the >
character, leading to >echo date
, which runs date
redirected to a file named echo
.
The above bug is obviously very different to the original shellshock bug. There are actually several problems:
() {
). CVE-2014-6271.() {
. CVE-2014-6271, CVE-2014-7169, all the other CVEs where a bug is triggered in bash's parser.select
/for
/while
), with checks for overflow. That stack is still corrupted. CVE-2014-7187.eol_ungetc_lookahead
on reset_parser
.BASH_FUNC_functionname%%
.The big problem here has been that every environment variable could be used as a vector for attack. Typically, attackers cannot control arbitrary environment variables, otherwise there are already other known attacks (think of LD_PRELOAD
, PATH
, IFS
, ...).
sudo
is not affected because it strips exported bash functions from the environment, as mentioned by Gilles on security.SE.
ssh
is affected. Typical sshd installations only allow a limited set of environment variables to be exported as configured in AcceptEnv in sshd_config
, e.g: LANG
and LC_*
. Even with this aggressive whitelisting approach, in shellshock any variable could be an attack vector.
Not only was every environment variable a potential attack vector, they exposed a >6000 lines parser.
system
, popen
, and others are potentially dangerous. Not only should you take care with their arguments: even when the arguments are fixed at compile-time, the environment is a potential attack vector. Use fork()/execve()
, preferably with a clean environment (but at least restrict the environment to white-listed variables, preferably with their values sanity-checked). Remember that a good quality system does what it is supposed to do, while a secure system does what it is supposed to do and nothing more. Invoking a full-blown shell makes doing nothing more a little bit harder.
Complexity is the enemy of security. These days you can easily find people recommending simpler shells. Most shells are free from shellshock by not supporting exported functions at all. Conversely, bash has received lots of security features over the years (you need to invoke it with -p
to avoid it dropping privileges on startup, it sanitizes IFS, ...), so don't assume I'm advocating switching shells, this is more of a general advice.
Some excerpts from David Wheeler's ancient "Secure Programming for Linux and UNIX HOWTO" chapter on environment variables are still worth rereading.
§5.2.3 ¶1:
For secure setuid/setgid programs, the short list of environment variables needed as input (if any) should be carefully extracted. Then the entire environment should be erased, followed by resetting a small set of necessary environment variables to safe values. There really isn't a better way if you make any calls to subordinate programs; there's no practical method of listing ``all the dangerous values''.
§5.2.3 ¶6:
If you really need user-supplied values, check the values first (to ensure that the values match a pattern for legal values and that they are within some reasonable maximum length).
Waving my hands a lot, I suspect the new exploit does the following:
>
combines with echo
as an output redirection for the bash
shellecho
being consumed by the evaluation to define the function, the only part of the -c
argument left to execute is date
, whose output goes to a file name echo
instead of standard output.That's the best I can come up with short of reading the bash
source, but I suspect the backslash facilitates some sort of buffer overflow that allows the environment string and the argument to -c
to be merged.
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