ShellShock - Yet Another Code Injection Vulnerability
ShellShock - Yet Another Code Injection Vulnerability
Written by Mike James   
Thursday, 25 September 2014

A vulnerability in the Bash shell has the Internet in full alarmed mode and like all good security holes it even has a catchy name - Shell Shock. How does it work?

shellalert

 

Commentators are calling it either the most important security hole since Heartbleed or more damaging than Heartbleed. If you are holding your breath for something really subtle and complicated, breath again. It is a glaring and very obvious code injection vulnerability of the sort we have been warning SQL users about since almost before SQL was invented. 

Bash, and most nix shells, are closer to macro processors than static languages, but don't let that lead you into believing that they aren't powerful. 

In this case the problem comes about because Bash uses environment variables to pass functions that are exported so that child processes can use them. Normally environment variables store simple data such as a string specifying the current working directory. Some applications make use of environment variables to pass data to Bash scripts and to other programs. For example, CGI stores the HTTP headers as environment variables.

That is, environment variables are used to pass data between applications and the fact that an environment variable can also hold code should now be causing a red light to flash, because if you can pass in data and/or code this is a potential code injection hole. 

So for example in the Bash shell you could define a function:

myFun () { echo "a function";}

and you could call the function by writing:

myFun

which would produce the text:

a function

The problem is that when you define a function Bash has no way of working out when the string that defines the function has completed its task - so it interprets the string to the very end.

For example, if you append a command to the end of the function it will be obeyed when the function is defined:

myFun() { echo "a function";};echo vulnerable

this prints 

vulnerable

and the function is also defined. 

This seems like a harmles quirk, until you remember that functions can be exported as environment variables for use by child shells. In this case it becomes very apparent that this is a way of executing a command in the child shell.  

First we need to export a variable set to the string that represents the function with the additional command payload tagged onto the end. 

export myFun='() { echo "a function";};echo vulnerable'

Now myFun exists as a string in the environment as you can prove using:

echo myFun

which displays the string. 

If you now start a child shell that executes the function it inherits via the environment:

bash -c myFun

you will see

vulnerable
a function

What is happening here is subtle. The "vulnerable" is displayed when the function is defined and the "a function" when the function is invoked. This is why the two strings are displayed in the wrong order.

Now we come to the final part of the jigsaw. When you start a child shell all environment functions are defined, even if they are not used. That is, if you try:

bash -c "echo hello world"

you will see 

vulnerable
hello world

That is, the payload has been executed even though the function was not called by the child shell.

What this means is that you can create a new environement variable that stores a function, i.e. an environement function with any name you care to pick, and the extra payload will be executed, even though the child shell doesn't call this new function.

That is, you have implemented a code injection.

Given that HTTP CGI, OpenSSH and other applications communicate with shell scripts etc via environment variables, you can see that it is possible to inject code during a standard transaction.

For example, an HTTP header like:

http-header[Host] = () { :; }; echo vulnerable

would cause the payload, in this case the echo, when any shell that inherited the environment was loaded.

How serious is the problem?

As always, it is difficult to say because any security hole is capable of being widened given time. 

As it stands the payload runs at the security level of the process which is unlikely to have root privileges. This should limit the damage unless a way to elevate the payload's status can be implemented. 

There have been reports of exploits being found in the wild, but as yet not much definite information exists. 

Given the simple fact that any Linux website that uses any sort of CGI script hosted by Bash is vulnerable to the attack this is a problem that needs attention immediately.

A patch for Bash has been issued, but there seem to be some problems remaining after the patch has been applied. 

It seems crazy that at this late stage, the Bash shell isn't new software, we are still falling victim to code injection. Using the same transport mechanism, i.e. environment variables for both external data and internal code, is the real cause of the problem. It seems likely that a solution can be found by restricting the form of environment functions so that no additional payload can be attached, but the real solution is to find another mechanism for sharing code between shell instances. 

shellalert

Banner


Do We Need Software Heroes?
30/10/2017

The super developer is a well-known stereotype, and perhaps one we rely on and even worship - a little too much. New research suggests that the hero may be more essential than we could have hoped for. [ ... ]



Prepare to Run a Code Club with Future Learn
21/11/2017

The Raspberry Pi Foundation has just opened the doors on a new free, short online course on the Future Learn platform. The aim of 'Prepare to Run a Code Club' is to assist new volunteers who want [ ... ]


More News

 

 
 

 

blog comments powered by Disqus

 

 

Last Updated ( Thursday, 25 September 2014 )
 
 

   
Banner
Banner
RSS feed of news items only
I Programmer News
Copyright © 2017 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.