What’s shellshock?
Shellshock (also known as Bashdoor) is a vulnerability in GNU bash shell. It allows an attacker access to run remote commands on your system. It seems to affect the Bash versions 1.13 to 4.3. In the past few days, botnets have used compromised computers for distributed denial-of-service (DDOS) attacks and vulnerability scanning. Bash is installed as the default command line interface on many Unix-based systems. It is used to interpret commands and is itself a command which can be executed. As such it has both a list of environment variable and a list of internal functions. When launching a new bash interpreter, a new list of environment variables and functions can be exported to the new process. This vulnerability causes Bash to execute commands stored in environment variables in a special way. This happens when a newly started instance of Bash scans its environment variables for values in a special format, which should be converted to internal functions. In the affected versions, Bash creates fragments of code on-the-fly and executes them without checking whether the fragments are only function definitions. Using this vulnerability, the attacker can execute any arbitrary command.
How to check whether you are affected?
In order to check whether your system is affected you can execute the following from a shell:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
If the ouput contains “vulnerable”, you are affected. Otherwise, it means the patch for Bash has already been installed (but keep in mind that there different ways to exploit this vulnerability and even if this check is negative, it’d be safe to update to newer versions of Bash as they are released).
Your server is not only vulnerable when spawning a Bash instance from the command line but also when Apache is used in combination with mod_cgi and spawns either a Bash shell or anything else (e.g. a Perl script) which executes commands and passes environment variables.
A few examples are:
- A Perl script using the built-in functions exec or system to invoke a new shell process
- A PHP script using the built-in functions exec or system to invoke a new shell process
- A Python script using os.system or os.popenx (depending on how it is called)
Note that an attack on CGI scripts will only work if Bash is used as default shell.
Just to show you how easy it is to use this vulnerability against a server running Apache, mod_cgi and some CGI scripts spawning a shell:
curl "https://mysiteipaddress.com/index.cgi" --insecure -H "User-Agent: () { :; }; echo 'Hello Server' > /tmp/shellshock.log"
This will return some HTML code and will create a file /tmp/shellshock.log on the affected server.
How to fix it?
In most systems, it’s as easy as installing the latest Bash update. On Debian, Ubuntu and other systems using apt-get:
apt-get update && apt-get upgrade
On Red Hat, Fedory, CentOS and other systems using yum:
yum -y update bash
On Arch Linux:
pacman -Syu
On SLES:
zypper ref -s
zypper up bash
SUSE Linux Enterprise Server
Note that updatse for SLES are only available in LTSS versions and for SLES 11 SP3. If you are running an older non-LTSS version of SLES, you’ll have to install Bash from source as described below. Here the list of SLES versions for which an update is available:
- SUSE Linux Enterprise Server 10 SP3 LTSS
- SUSE Linux Enterprise Server 11 SP2 LTSS
- SUSE Linux Enterprise Server 11 SP1 LTSS
- SUSE Linux Enterprise Server 10 SP4 LTSS
- SUSE Linux Enterprise Server 11 SP3
Red Hat Enterprise Linux
RHEL updates are available for the following versions:
- Red Hat Enterprise Linux 4 Extended Lifecycle Support
- Red Hat Enterprise Linux 5
- Red Hat Enterprise Linux 5.6 Long Life
- Red Hat Enterprise Linux 5.9 Extended Update Support
- Red Hat Enterprise Linux 6
- Red Hat Enterprise Linux 6.2 Advanced Update Support
- Red Hat Enterprise Linux 6.4 Extended Update Support
- Red Hat Enterprise Linux 7
Mac OS X
Apple has released updates for Mac OS X Lion, Mountain Lion and Mavericks. Make sure that you install these updates even if Apple has been arguing that most Mac OS X users are not exposed unless they have configured advanced UNIX services. Since most Max OS X users do not have a web server running, the risk of having this vulnerability exploited is not as high as for Unix-based web servers accessible from the internet but you do not want to risk anything especially when the fix is as easy as updating your software (which should be done on a regular basis anyway).
How to install from source?
Latest Bash version (4.3)
If no update is available for your system (e.g. because you’re on an older version), you’ll have to download Bash 4.3, apply all patches, compile it and install it. If you have a direct access from your machine to the internet, do the following:
cd /tmp
mkdir bash
cd bash
wget https://ftp.gnu.org/gnu/bash/bash-4.3.tar.gz
for i in $(seq -f "%03g" 1 27); do wget https://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-$i; done
tar zxvf bash-4.3.tar.gz
cd bash-4.3
for i in $(seq -f "%03g" 1 27);do patch -p0 < ../bash43-$i; done
./configure && make && make install
If there are more than 27 patches for Bash 4.3 when you read this replace both occurences of 27 by the appropriate number.
If you do not have direct access to the internet from the machine, you’ll have to download Bash 4.3 and all updates and then copy them through (S)FTP to /tmp/bash:
- First create the directory /tmp/bash using: mkdir /tmp/bash
- Then download https://ftp.gnu.org/gnu/bash/bash-4.3.tar.gz
- Then go to https://ftp.gnu.org/gnu/bash/bash-4.3-patches/ and download all files from bash43-001 to the latest patch (currently bash43-027).
- Upload all downloaded files to /tmp/bash
- Go to /tmp/bash using: cd /tmp/bash
- Execute the following:
tar zxvf bash-4.3.tar.gz
cd bash-4.3
for i in $(seq -f "%03g" 1 27);do patch -p0 < ../bash43-$i; done
./configure && make && make install
Note: If the files are renamed to bash43-0xx.txt when downloading, you’ll have to remove the .txt extension. And change 27 to the current number of patches for Bash 4.3.
Also note that bash will be installed in /usr/local/bin/bash. you will then need to make sure that the old bash is removed and replaced by a symlink to the new one:
cd /bin; rm bash; ln -s /usr/local/bin/bash
(thanks Gerhard for the hint)
Older Bash version (e.g. 3.2)
If you’re using an older version of Bash (e.g. because you’re running SLES 11 SP1), you might want to only update Bash to the latest update within the same version.
First create the working directory /tmp/bash using: mkdir /tmp/bash
Download https://ftp.gnu.org/gnu/bash/bash-3.2.48.tar.gz instead of the 4.3 package. This package already includes the updates until update 48. Additionally download updates 49 to 54 from https://ftp.gnu.org/gnu/bash/bash-3.2-patches/.
Note: If the files are renamed to bash32-0xx.txt when downloading, you’ll have to remove the .txt extension.
Upload all downloaded files to /tmp/bash. Go to /tmp/bash using: cd /tmp/bash and execute the following:
tar zxvf bash-3.2.48.tar.gz
cd bash-3.2.48/
for i in $(seq -f "%03g" 49 54);do patch -p0 < ../bash32-$i; done
./configure && make && make install
Change 54 to the current number of patches for Bash 3.2.
Also note that this uses the patch command. If it is not installed, you’ll have to install it or you’ll have to perform all steps except the last one on a machine where patch is installed and then copy the resulting folder to the machine where it should be installed before executing the last command. Before executing this last command you might need to add execution permissions to the configure file:
chmod +x configure
If you get the following error message during the install step:
/home/install -m 0755 bash /usr/local/bin/bash
make: execvp: /home/install: Permission denied
make: *** [install] Error 127
You will have to execute the following:
install -m 0755 bash /usr/local/bin/bash
Note that bash will be installed in /usr/local/bin/bash. you will then need to make sure that the old bash is removed and replaced by a symlink to the new one:
cd /bin; rm bash; ln -s /usr/local/bin/bash
(thanks Gerhard for the hint)
LD_LIBRARY_PATH
I’ve noticed that with the new version of Bash there may be some issues when setting LD_LIBRARY_PATH before starting some software. Actually you should not be using LD_LIBRARY_PATH on a production system but rather rely on ldconfig. In order to do this, you should add all directories containing shared libraries to /etc/ld.so.conf and execute the following:
ldconfig -v
This way you make sure that even with an updated version of Bash your software will find the shared libraries without issues.