If you are not aware, there is a critical bug in Bash that causes an attacker to craft an attack using environment variables. While a partial patch has been released on Linux, Apple has yet to release a patch. However, there is a fix for it and I came up with a script to automate the process.
This will work on Mavericks. Mountain Lion might work with this patch. Do not run on Yosemite Beta since it uses a newer version.
bashupgrade.sh usage:
- -c : checks if your version of bash is vulnerable by the bug.
- -i : compiles and install patch.
Note: You must install XCode and Command Line Tools before executing this script. This script also has to be run as root.
When Apple releases an official patch, please install that and verify.
Note: The script has been upgraded to patch CVE-2014-7169 with additional checks.
Update: Fix will work in Leopard (as long XCode 3.1.2 is installed), meaning it will work in Snow Leopard and Lion as well.
Before:
After:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# OS X Bash Patch Script rev 3 | |
# By James M. (chikorita157). http://chikorita157.com | |
# BSD License | |
##################################################### | |
function show_usage { | |
echo "How to use: bashupgrade.sh (arg)" | |
echo "-i – Compile and install patched bash binary." | |
echo "-c – Checks the bash vulnerability" | |
echo "This is only for OS X users. You must have XCode and Command Tools installed before using this script. Otherwise, it will fail." | |
} | |
if [[ $1 = -c ]]; then | |
# Check script based on https://github.com/hannob/bashcheck/blob/master/bashcheck | |
[ -n "$1" ] && bash=$(which $1) || bash=$(which bash) | |
echo -e "\033[95mTesting $bash …" | |
echo $($bash –version | head -n 1) | |
echo -e "\033[39m" | |
r=`env x="() { :; }; echo x" $bash -c "" 2>/dev/null` | |
if [ -n "$r" ]; then | |
echo -e '\033[91mVulnerable to CVE-2014-6271 (original shellshock)\033[39m' | |
else | |
echo -e '\033[92mNot vulnerable to CVE-2014-6271 (original shellshock)\033[39m' | |
fi | |
cd /tmp;rm echo 2>/dev/null | |
env x='() { function a a>\' $bash -c echo 2>/dev/null > /dev/null | |
if [ -e echo ]; then | |
echo -e "\033[91mVulnerable to CVE-2014-7169 (taviso bug)\033[39m" | |
else | |
echo -e "\033[92mNot vulnerable to CVE-2014-7169 (taviso bug)\033[39m" | |
fi | |
$($bash -c "true $(printf '<<EOF %.0s' {1..80})" 2>/tmp/bashcheck.tmp) | |
ret=$? | |
grep -q AddressSanitizer /tmp/bashcheck.tmp | |
if [ $? == 0 ] || [ $ret == 139 ]; then | |
echo -e "\033[91mVulnerable to CVE-2014-7186 (redir_stack bug)\033[39m" | |
else | |
echo -e "\033[92mNot vulnerable to CVE-2014-7186 (redir_stack bug)\033[39m" | |
fi | |
$bash -c "`for i in {1..200}; do echo -n "for x$i in; do :;"; done; for i in {1..200}; do echo -n "done;";done`" 2>/dev/null | |
if [ $? != 0 ]; then | |
echo -e "\033[91mVulnerable to CVE-2014-7187 (nested loops off by one)\033[39m" | |
else | |
echo -e "\033[96mTest for CVE-2014-7187 not reliable without address sanitizer\033[39m" | |
fi | |
$($bash -c "f(){ x(){ _;};x(){ _;}<<a;}" 2>/dev/null) | |
if [ $? != 0 ]; then | |
echo -e "\033[91mVulnerable to CVE-2014-6277 (lcamtuf bug #1) [no patch]\033[39m" | |
else | |
echo -e "\033[92mNot vulnerable to CVE-2014-6277 (lcamtuf bug #1)\033[39m" | |
fi | |
if [ -n "$(env x='() { _;}>_[$($())] { echo x;}' $bash -c : 2>/dev/null)" ]; then | |
echo -e "\033[91mVulnerable to CVE-2014-6278 (lcamtuf bug #2) [no prefix/suffix]\033[39m" | |
elif [ -n "$(env BASH_FUNC_x%%='() { _;}>_[$($())] { echo x;}' $bash -c : 2>/dev/null)" ]; then | |
echo -e "\033[91mVulnerable to CVE-2014-6278 (lcamtuf bug #2) [prefix/%%-suffix]\033[39m" | |
elif [ -n "$(env 'BASH_FUNC_x()'='() { _;}>_[$($())] { echo x;}' $bash -c : 2>/dev/null)" ]; then | |
echo -e "\033[91mVulnerable to CVE-2014-6278 (lcamtuf bug #2) [prefix/()-suffix]\033[39m" | |
else | |
echo -e "\033[92mNot vulnerable to CVE-2014-6278 (lcamtuf bug #2)\033[39m" | |
fi | |
r=`a="() { echo x;}" $bash -c a 2>/dev/null` | |
if [ -n "$r" ]; then | |
echo -e "\033[93mVariable function parser still active, maybe vulnerable to unknown parser bugs\033[39m" | |
else | |
echo -e "\033[92mVariable function parser inactive, likely safe from unknown parser bugs\033[39m" | |
fi | |
exit 0 | |
fi | |
if [ "$(id -u)" != "0" ]; then | |
echo "Please run the script as root." | |
exit 1 | |
else | |
if [[ $1 = -i ]]; then | |
cd /tmp | |
mkdir bash-fix | |
cd bash-fix | |
echo "Downloading bash source code…" | |
curl https://opensource.apple.com/tarballs/bash/bash-92.tar.gz | tar zxf – | |
cd bash-92/bash-3.2 | |
echo "Downloading patch and applying…" | |
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 | |
curl https://ftp.gnu.org/pub/gnu/bash/bash-3.2-patches/bash32-054 | patch -p0 | |
curl https://ftp.gnu.org/pub/gnu/bash/bash-3.2-patches/bash32-055 | patch -p0 | |
curl https://ftp.gnu.org/pub/gnu/bash/bash-3.2-patches/bash32-056 | patch -p0 | |
cd .. | |
echo "Building…" | |
xcodebuild > /dev/null 2>&1 | |
if [ $? = 0 ]; then | |
echo "Build Successful!" | |
else | |
echo "Build Failed (Build error or XCode not installed), aborting…" | |
echo "Removing temp files…" | |
rm -rf /tmp/bash-fix | |
exit 1 | |
fi | |
if [ -f "/bin/bash.old" ] && [ -f "/bin/bash.old" ]; then | |
echo "Backup exists, skipping…" | |
else | |
echo "Backing up old versions…" | |
cp /bin/bash /bin/bash.old | |
cp /bin/sh /bin/sh.old | |
fi | |
echo "Checking versions…" | |
build/Release/bash –version # GNU bash, version 3.2.56(1)-release | |
build/Release/sh –version # GNU bash, version 3.2.56(1)-release | |
while true; do | |
read -p "Do you want to replace the existing version with the fixed version? " yn | |
case $yn in | |
[Yy]* ) cp build/Release/bash /bin; cp build/Release/sh /bin; chmod a-x /bin/bash.old /bin/sh.old; break;; | |
[Nn]* ) echo "Aborting"; exit 1; break;; | |
esac | |
done | |
echo "Bash has been patched." | |
bash –version | |
echo "Removing temp files…" | |
rm -rf /tmp/bash-fix | |
exit 0 | |
else | |
echo "Invalid arguments." | |
show_usage; | |
exit 1 | |
fi | |
fi |
Leave a Reply