How do I recompile Bash to avoid Shellshock (the remote exploit CVE-2014-6271 and CVE-2014-7169)?
Solution 1:
Status
Apple has released Bash security fixes for Shellshock and related vulnerabilities as "OS X bash Update 1.0". They can be installed through normal system update for people using OS X Mountain Lion v10.8.5 or OS X Mavericks v10.9.5 (they are included in Security Update 2014-005) and can also be installed manually. Official Apple fixes are also available for OS X Lion v10.7.5 and OS X Lion Server v10.7.5 but those are only available via manual download. The security fixes are available via different URLs based on the operating system version:
- http://support.apple.com/kb/DL1769 - Mavericks (10.9.5 and above)
- http://support.apple.com/kb/DL1768 - Mountain Lion (10.8.5)
- http://support.apple.com/kb/DL1767 - Lion & Lion Server (10.7.5)
(If new patches are released, put them here but please keep these existing ones as well for reference.)
The Apple patch takes care of Shellshock and several other vulnerabilities and is fine for most people. tl;dr people can stop reading here.
HOWEVER, the attention drawn to bash by the Shellshock bug has caused many researchers to take a hard look at bash and more and more (hard to exploit) vulnerabilities keep being found. If you are highly concerned about security (because maybe you are running OS X Server to host a publicly available web site) then you may want to (try to) keep up with the vulnerabilities and patches as they keep rolling in by compiling bash yourself. Otherwise, don't worry about it.
Look for Apple to release another update to bash some time in the future when the dust settles on finding further vulnerabilities.
An official set of patches of bash itself for bash 3.2, patches 52, 53, and 54 (which correspond to Bash 4.3 patches 25, 26, and 27) are available which fix both CVE-2014-6271 and CVE-2014-7169, as well as the 'Game over' displayed below. This has been tested by me (@alblue) and the post has been updated accordingly (and then additional updates were made: see revision 41 for the post that stops at patch 54).
Many additional vulnerabilities have been reported against bash. According to Michal Zalewski's post if you have patch 54 (and presumably Apple's official patch) "there's no point in obsessing about the status of these individual bugs, because they should no longer pose a security risk:"
CVE-2014-6271 - original RCE found by Stephane. Fixed by bash43-025 and corresponding Sep 24 entries for other versions.
CVE-2014-7169 - file creation / token consumption bug found by Tavis. Fixed by bash43-026 & co (Sep 26)
CVE-2014-7186 - a probably no-sec-risk 10+ here-doc crash found by Florian and Todd. Fixed by bash43-028 & co (Oct 1).
CVE-2014-7187 - a non-crashing, probably no-sec-risk off-by-one found by Florian. Fixed by bash43-028 & co (Oct 1).
CVE-2014-6277 - uninitialized memory issue, almost certainly RCE found by Michal Zalewski. No specific patch yet.
CVE-2014-6278 - command injection RCE found by Michal Zalewski. No specific patch yet.
It gets pretty confusing. Fortunately Chet Ramey, the official bash maintainer, posted a CVE to patch mapping. His post refers to patches for bash 4.3, I (@OldPro) have translated them to patches for bash 3.2, which is what is applicable to OS X. Also, since this post he has released patch 57, so I added that below:
bash32-052 CVE-2014-6271 2014-09-24
bash32-053 CVE-2014-7169 2014-09-26
bash32-054 exported function namespace change 2014-09-27 ("Game Over")
bash32-055 CVE-2014-7186/CVE-2014-7187 2014-10-01
bash32-056 CVE-2014-6277 2014-10-02
bash32-057 CVE-2014-6278 2014-10-05
See David A. Wheeler's post for a timeline and greater detail.
@alblue posted build instructions through patch 55. I (@OldPro) added patch 56 and 57 to the instructions but have not tested it.
Testing for the original Vulnerability
You can determine if you are vulnerable to the original problem in CVE-2014-6271 by executing this test:
$ env x='() { :;}; echo vulnerable' bash -c 'echo hello'
bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x'
hello
The above output is an example of a non-vulnerable bash
version. If you see the word vulnerable
in the output of that command your bash
is vulnerable and you should update. Below is a vulnerable version from OS X 10.8.5:
Testing for the new Vulnerability
There has been an update to the original post and Bash 3.2.52(1) is still vulnerable to a variation of the vulnerability, defined in CVE-2014-7169
$ rm -f echo
$ env X='() { (a)=>\' sh -c "echo date"; cat echo
sh: X: line 1: syntax error near unexpected token `='
sh: X: line 1: `'
sh: error importing function definition for `X'
Thu 25 Sep 2014 08:50:18 BST
The above output is an example of a vulnerable bash
version. If you see a date in the output of that command your bash
is vulnerable.
Disabling auto-imported functions to prevent "Game Over"
Researchers noted, without classifying it as a vulnerability, that a script could hijack a function in a subshell using auto-imported functions:
$ env ls="() { echo 'Game Over'; }" bash -c ls
Game over
The above code on an affected system would display Game Over
instead of the directory listing you would expect from ls
. Obviously, echo 'Game Over'
could be replaced by any nefarious code you want. This became know as the "Game Over" bug.
Prior to the availability of patch 54, both NetBSD and FreeBSD disabled auto-importing bash functions by default, partly to prevent "Game Over" but mainly to contain any further errors in the parser (such as CVE-2014-7169) as they were continuing to be discovered, and added a new command line flag --import-functions
to re-enable the old default behavior. I (@alblue) have prepared a patch (against 3.2.53) for others to use if they want to adopt this behaviour as well and have included it below. By default this patch is not enabled in the build script below. I (@OldPro) believe this patch is no longer necessary or a good idea, because it breaks backwards compatibility and the vulnerabilities it protects against are very well addressed by patch 54 and earlier patches, and enabling this unofficial patch prevents future patches from being applied.
(Note to question editors; please do not enable this by default, as it is an unofficial patch.)
a0c5c4d66742fddd0a35001cb91798a5fbf8a2f5 import_functions.patch
The patch can be enabled by running export ADD_IMPORT_FUNCTIONS_PATCH=YES
before running the build. Note that enabling this patch will disable patch 54 and any future patches because future patches cannot be guaranteed to be compatible with the unofficial patch.
Apple Patch has Game Over vulnerability, sort of
As pointed out by @ake_____ on twitter the official Apple patch is still vulnerable to environment clobbering of executables:
$ env '__BASH_FUNC<ls>()'="() { echo Game Over; }" bash -c ls
Game Over
Users should decide for themselves how important this is. I (@OldPro) think it is nothing to worry about because there is no known exploit for this behavior (it was not even given a CVE identifier) because in general unprivileged remote attackers cannot set the name of an environment variable and attackers with privileges cannot use this to gain privileges they do not already have (at least not without exploiting an additional vulnerabiltiy).
To provide a little background, bash allows you to define functions, and furthermore allows you to export those functions to subshells via the export -f
command. This used to be implemented by creating an environment variable with the same name as the function with its value set to the function definition. So
$ ls () { echo 'Game Over'; }
$ export -f ls
$ echo $ls
Game Over
This happened because export -f ls
created an environment variable named ls
. The "Game Over" vulnerability was that you could directly create this environment variable without having to first define the function, which meant if you could inject the right variable name you could hijack a command. Apple tried to fix this by making it hard to create a variable with the right name. The official bash patch 54 actually makes it impossible to create a variable with the right name by using variable names that include %
which is a character not allowed in a variable name, effectively putting exported function definitions in a different, reserved namespace.
If none of the above makes sense to you, don't worry about it. You are fine with the Apple patch for now.
System Binaries
OS X 10.9.5 (the latest stable release at the moment) ships with Bash v3.2.51:
$ bash --version
GNU bash, version 3.2.51(1)-release (x86_64-apple-darwin13)
Copyright (C) 2007 Free Software Foundation, Inc.
You can obtain and recompile Bash as follows, providing that you have Xcode installed (and have run xcodebuild
at least once before to accept the license):
$ # If you want to disable auto-imported functions, uncomment the following
$ # export ADD_IMPORT_FUNCTIONS_PATCH=YES
$ mkdir bash-fix
$ cd bash-fix
$ curl https://opensource.apple.com/tarballs/bash/bash-92.tar.gz | tar zxf -
$ cd bash-92/bash-3.2
$ curl https://ftp.gnu.org/pub/gnu/bash/bash-3.2-patches/bash32-052 | patch -p0
$ curl https://ftp.gnu.org/pub/gnu/bash/bash-3.2-patches/bash32-053 | patch -p0
$ # See note above about ADD_IMPORT_FUNCTIONS_PATCH
$ [ "$ADD_IMPORT_FUNCTIONS_PATCH" == "YES" ] && curl http://alblue.bandlem.com/import_functions.patch | patch -p0
$ [ "$ADD_IMPORT_FUNCTIONS_PATCH" == "YES" ] || curl https://ftp.gnu.org/pub/gnu/bash/bash-3.2-patches/bash32-054 | patch -p0
$ [ "$ADD_IMPORT_FUNCTIONS_PATCH" == "YES" ] || curl https://ftp.gnu.org/pub/gnu/bash/bash-3.2-patches/bash32-055 | patch -p0
$ [ "$ADD_IMPORT_FUNCTIONS_PATCH" == "YES" ] || curl https://ftp.gnu.org/pub/gnu/bash/bash-3.2-patches/bash32-056 | patch -p0
$ [ "$ADD_IMPORT_FUNCTIONS_PATCH" == "YES" ] || curl https://ftp.gnu.org/pub/gnu/bash/bash-3.2-patches/bash32-057 | patch -p0
$ cd ..
$ # Note: DO NOT ADD SUDO TO XCODEBUILD HERE
$ xcodebuild
$ build/Release/bash --version # GNU bash, version 3.2.57-release
$ build/Release/sh --version # GNU bash, version 3.2.57-release
$ sudo cp /bin/bash /bin/bash.old
$ sudo cp /bin/sh /bin/sh.old
$ sudo cp build/Release/bash /bin
$ sudo cp build/Release/sh /bin
(Note: you can run this by copy-and-pasting the above code block, going into Terminal and then running pbpaste | cut -c 2- | sh
. Always take care when running random scripts from the internet though ...)
After this, the Bash version should be v3.2.57:
$ bash --version
GNU bash, version 3.2.57-release (x86_64-apple-darwin13)
Copyright (C) 2007 Free Software Foundation, Inc.
For security, and after testing, I recommend that you chmod -x
the old versions to ensure they aren't re-used, or move them to a backup site.
$ sudo chmod a-x /bin/bash.old /bin/sh.old
Other answers have solutions for those using MacPorts or Homebrew; these don't fix the problem, they just install additional versions of Bash. Please see those answers if you want to upgrade those specifically.
Thanks
Thanks to Chet, who looks after bash, and has been making these patches available. Thanks to everyone else who has commented on this and improved it over time.
Now Apple has released the real fix, though this might still be useful. Because they only released a fix for Lion and up, and the official patch provides GNU bash, version 3.2.53(1)-release (x86_64-apple-darwin13), however, the Game over bug is still somewhat vulnerable. At this point, rebuilding your own version of Bash against 3.2.57 is probably more secure than relying on Apple's patch, unless you do it wrong.
Solution 2:
Macports
This gets you a bash version 4.3.28(1) which patched both vulnerabilities (CVE-2014-6271 and CVE-2014-7169) as well as some subsequently discovered ones. This is useful if you have changed shells to use Macports bash to get the version 4 features.
It will not solve the issue of standard OS scripts as the have #!/bin/sh
or #!/bin/bash
as the first line. This sort of issue is why Macports tries not to use Apple's supplied versions of programs as Macports tends to be updated quicker e.g. it has a newer version of bash)
You can make terminal use this as in the Homebrew answer
To install macports follow these instructions which are
1. Install Xcode and the Xcode Command Line Tools
2. Agree to Xcode license in Terminal: sudo xcodebuild -license
3. Download MacPorts pkg for your version of OS X: links are on the page
4. Run the pkg
When you have macports installed you need to latest versions, this is done by running
sudo port selfupdate
and recompile or get the latest binaries by
sudo port upgrade outdated
Solution 3:
NOTE regarding the official Apple OS X bash Update 1.0: This software update only brings the official Apple bash version to 3.2.53. The 3.2.54 patch revision offers the following change:
This patch changes the encoding bash uses for exported functions to avoid clashes with shell variables and to avoid depending only on an environment variable's contents to determine whether or not to interpret it as a shell function.
For users who have already patched the system with 3.2.54 binaries, you may either replace your compiled binaries with the Apple patch or you can leave things as they are but it is ill-advised. Although Apple left their binary versioning at 3.2.53, the Apple patch DOES contain the fix for the below exploit test:
env X='() { (a)=>\' sh -c "echo date"; cat echo
This means that the Apple official 3.2.53 binary contains equivalent security to the vanilla GNU 3.2.54 binary. An unfortunate point of confusion, but it is what it is. Apple's fix is not half-baked. It appears to be a complete fix for the problem. As such, the below roadmap to compiling vanilla bash
and sh
from GNU source should be considered a historic artifact and possibly consulted as a template for how to do patches in the future should they be necessary.
NOTE: With the vanilla GNU source, sh
has privilege elevation problems that cause failures in various installers, e.g., Adobe Flash. I strongly recommend sticking with the Apple-patched binaries. Consider this patch scheme to be deprecated and ill-advised.
There is a new GNU bash 3.2.55 patch that describes the following fix:
Bug-Description:
There are two local buffer overflows in parse.y that can cause the shell to dump core when given many here-documents attached to a single command or many nested loops.
We leave it up to the gentle reader to determine whether to sit with the official Apple-patched binaries or roll your own to deal with the new possible exploits. Personally, I will be sticking with the Apple binaries.
This post details how to compile and install a vanilla bash
and sh
on OS X. I chose this route as following examples detailing using Apple-specific source did not leave me with the correct patch revision. YMMV. This vanilla installation is, however, targeted at replacing the OS X binaries such that when Apple does finally release a security update, these vanilla replacements will be usurped by by their proper Apple counterparts.
My base configuration is:
OS X Lion 10.7.5 and Xcode 4.6.3 with all command-line utilities installed.
My steps to fix this were:
Download the base bash source code for 3.2.48 from:
https://ftp.gnu.org/gnu/bash/bash-3.2.48.tar.gz
Download the bash3.2.49, .50, .51, .52, .53, .54 and .55 patches from:
https://ftp.gnu.org/gnu/bash/bash-3.2-patches/
I saved them as $filename.patch, e.g., bash3.2.50.patch.
CD into your download directory and …
Unpack the main source branch:
tar xzvf bash-3.2.48.tar.gz
cd bash-3.2.48
Assuming that you've renamed your downloaded patch files as described earlier,
cp ../*.patch .
Then …
for file in *.patch ; do
patch -p0 < $file
done
This should show successful patches of various files. If not, be prepared to do some exploration and investigation.
Next:
sudo cp /bin/bash /bin/bash_old
sudo cp /bin/sh /bin/sh_old
sudo chmod -x /bin/bash_old
sudo chmod -x /bin/sh_old
That basically backed up your old, vulnerable bash and sh shells and removed their executable privilege. That gives you the capacity to restore the commands as necessary, but removes their ability to do damage in the meantime.
Next:
./configure --prefix=/ ; make ; sudo make install
This should correctly configure, compile and install the new bash binary into /bin. After it's done, exit Terminal and reopen.
You should, all things happy and smiling, be able to bash --version
and now see 3.2.55, e.g.:
Gaia:Downloads trane$ bash --version
GNU bash, version 3.2.55(1)-release (i386-apple-darwin11.4.2)
Copyright (C) 2007 Free Software Foundation, Inc.
The exact output in the command above will differ depending on your version of OS X.
You should also be able to test your vulnerability against bash
and find that it is fine.
NOTE: We've only fixed bash so far, but the /bin/sh
executable is still in its vulnerable state. Merely copying bash
atop sh
is a Linux style of doing things. OS X's sh
implementation has some differences from bash
, however, so you'll want to drag out the compiler again. Further information on how bash
and sh
differ in OS X can be found here:
https://apple.stackexchange.com/a/89327/91441
In your download directory do:
make clean
In your favourite editor, open the file Makefile.in
and scroll to line 99. We're going to change the Program line so that the binary we output is sh
instead of bash
like so:
Program = sh$(EXEEXT)
Save it and then
./configure --prefix=/ --enable-xpg-echo-default --enable-strict-posix-default
make ; sudo make install
Now you'll have built sh
almost exactly as Apple would.
One final note: On some (all?) systems, Apple generally seems to place the bashbug
executable in /usr/bin
. Our compile will have put it into /bin
. So, the final steps here:
sudo mv /usr/bin/bashbug /usr/bin/bashbug_old
sudo chmod -x /usr/bin/bashbug_old
sudo mv /bin/bashbug /usr/bin/bashbug
Solution 4:
For anyone struggling with compiling from source, as of September 29th, Apple has officially released patches for Mac OS X 10.9.5, 10.8.5 as well as 10.7.5:
- OS X bash Update 1.0 – OS X Mavericks
- OS X bash Update 1.0 – OS X Mountain Lion
- OS X bash Update 1.0 - OS X Lion
Solution 5:
First, patching bash and sh for this vulnerability is likely to break some scripts on your Mac. You really don't need to do this unless you are are offering web services to the public internet directly from your Mac. So if it is really not necessary, wait until there is an official security update from Apple.
Being warned, here are some instructions on how to do this update using Brew on Mavericks 10.9.
First confirm that you are using an outdated bash:
$ which bash
/bin/bash
$ /bin/bash --version
GNU bash, version 3.2.51(1)-release (x86_64-apple-darwin13)
Copyright (C) 2007 Free Software Foundation, Inc.
The most current bash is 4.3.25
If you don't have Xcode installed, you'll need the Xcode command line tools, which can be installed by
$ xcode-select --install
Or from the developer portal.
To install Brew (http://brew.sh):
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Then do:
$ brew doctor
Follow any instructions if there are problems. Many common problems are addressed here.
Then update brew to the latest list of packages:
$ brew update
To get the latest bash 4.3.25:
$ brew install bash
This installs bash into /usr/local/Cellar/bash/4.3.25/bin/bash
The old bash
and sh
still exists at /bin
, so after installing you'll rename the old executables to a new file.
$ sudo mv /bin/bash /bin/bash_old
$ sudo mv /bin/sh /bin/sh_old
If you are very paranoid, you can remove execute permissions on the bash_old
$ sudo chmod a-x /bin/bash_old /bin/sh_old
Then create a symbolic link to the new bash 4.3.25 that brew installed.
$ sudo ln -s /usr/local/Cellar/bash/4.3.25/bin/bash /bin/bash
$ sudo ln -s /usr/local/Cellar/bash/4.3.25/bin/bash /bin/sh
Reboot and it is complete.
A warning — this may break some existing shell scripts that might rely on bash 3.2 or the differences that the Mac sh
has over the linux sh
. There is a much more sophisticated answer to replacing bash and sh from sources, from an answer by @TraneFranks in this same thread.