-
-
Save mattwhite/86de50d30134129e44ef to your computer and use it in GitHub Desktop.
# inspired by http://askubuntu.com/a/528171 and the comments below | |
# build bash 3.2, though this should work for other versions as well | |
BASH_MAJOR=3 | |
BASH_MINOR=2 | |
# prerequisites | |
sudo apt-get install build-essential gettext bison | |
# get bash source | |
mkdir src && cd src | |
wget https://ftp.gnu.org/gnu/bash/bash-$BASH_MAJOR.$BASH_MINOR.tar.gz | |
tar zxvf bash-$BASH_MAJOR.$BASH_MINOR.tar.gz | |
cd bash-$BASH_MAJOR.$BASH_MINOR | |
# download, verify, and apply all available patches, which as of 2014-10-02 | |
# include patches for CVE-2014-6271, CVE-2014-7169, CVE-2014-6277, CVE-2014-6278 | |
# CVE-2014-7186, and CVE-2014-7187. | |
wget -nv -r 1 -nH -nd -np https://ftp.gnu.org/gnu/bash/bash-$BASH_MAJOR.$BASH_MINOR-patches/ | |
wget -nv https://ftp.gnu.org/gnu/gnu-keyring.gpg | |
for i in bash$BASH_MAJOR$BASH_MINOR-???; do | |
if gpg --verify --keyring ./gnu-keyring.gpg $i.sig; then | |
if ! patch -p0 < $i; then | |
echo "patch $i failed" | |
exit 1 | |
fi | |
else | |
echo "patch $i has a bad signature" | |
exit 2 | |
fi | |
done | |
# compile and install to /usr/local/bin/bash | |
./configure && make | |
sudo make install | |
# point /bin/bash to the new binary | |
if /usr/local/bin/bash -c 'true'; then | |
if [ ! -f /bin/bash.old ]; then | |
sudo mv /bin/bash /bin/bash.old | |
sudo ln -s /usr/local/bin/bash /bin/bash | |
fi | |
else | |
echo "bash not installed correctly!" | |
exit 3 | |
fi | |
# test each of the exploits on the old version of bash | |
echo "OLD BASH:" | |
env x='() { :;}; echo VULNERABLE to CVE-2014-6271' /bin/bash.old -c echo | |
env x='() { (a)=>\' /bin/bash.old -c "echo echo TEST" 2>/dev/null; cat echo 2>/dev/null; rm -f ./echo; echo "If you see 'echo TEST' above you are ok, if you just see 'TEST' you are VULNERABLE to CVE-2014-7169" | |
/bin/bash.old -c 'true <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF' || echo "VULNERABLE to CVE-2014-7186" | |
(for x in {1..200} ; do echo "for x$x in ; do :"; done; for x in {1..200} ; do echo done ; done) | /bin/bash.old || echo "VULNERABLE to CVE-2014-7187" | |
# test each of the exploits on the new version of bash | |
echo "NEW BASH:" | |
env x='() { :;}; echo Vulnerable to CVE-2014-6271' bash -c echo | |
env x='() { (a)=>\' bash -c "echo echo TEST" 2>/dev/null; cat echo 2>/dev/null; rm -f ./echo; echo "If you see 'echo TEST' above you are ok, if you just see 'TEST' you are VULNERABLE to CVE-2014-7169" | |
bash -c 'true <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF' || echo "VULNERABLE to CVE-2014-7186" | |
(for x in {1..200} ; do echo "for x$x in ; do :"; done; for x in {1..200} ; do echo done ; done) | bash || echo "VULNERABLE to CVE-2014-7187" | |
echo "NOTE: CVE-2014-6277 and CVE-2014-6278 should be mitigated by these patches as well, but there is not yet a test for them." |
Thanks a log.
I had to install make, gcc, patch
May want to check that it's built correctly before doing the mv line. I didn't have make installed, so the compile step failed, but then it moved my existing bash to bash.old and didn't replace it with a newer one!
Thank you!
I patched it, and when I tested the actual bash the response was:
env: bash: No such file or directory
Is it normal?
Thank you.
It does not fix the problem completly:
http://www.smittix.co.uk/shellshock-becomes-aftershock-as-previous-bash-patch-incomplete/
To apply the final patch:
- After it gets uploaded to http://ftp.gnu.org/gnu/bash/bash-3.2-patches/ (look for bash32-053):
Change line
for i in $(seq -f "%03g" 1 52); do
to
for i in $(seq -f "%03g" 1 53); do
- If you do not want to wait, you can download the patch from http://seclists.org/oss-sec/2014/q3/734 (Attachment: bash32-053)
Manually execute the commands from the original script until you get to
compile and install to /usr/local/bin/bash
Then do:
wget http://seclists.org/oss-sec/2014/q3/att-734/bash32-053.bin
mv bash32-053.bin bash32-053
patch -p0 < bash32-053
Then continue with the next commands in the original script
I made a temporary solution, feel free to use it while waiting:
https://gist.github.com/ChrisRuss/f2eb63686540ed9b00f6
Ok, I have updated the gist with the improvements from @href, @stephankoelle, and @Wol. The patch for CVE-2014-7169 is available now, so I've included that as well.
Thanks for updates. I really appreciate it.
This is awesome. Could you update line 15 once again?
There's now bash32-054 27-Sep-2014 22:37 6.5K
on ftp.gnu.org.
Thank you for this.
Thanks @sodabrew, I updated it.
Why not going for a full download of all patches? Current solution needs fixing for every new patch that appears. My idea is to download the full patches folder and someone at ycombinator (https://news.ycombinator.com/item?id=8374948) had the same idea:
wget -r -l1 -nH -nd -np http://ftp.gnu.org/gnu/bash/bash-4.3-patches/ && rm *.sig index.html
cd bash-4.3
for i in ../bash43-*; do patch -p0 < $i; done
Maybe get rid of the static bash-version, too so one can apply the same script to some newer (or older) bash later on.
Above code is just deleting the *.sig, but one can easily extend the for-loop like this (untested):
for i in ../bash43-???; do
if gpg --verify --keyring ./gnu-keyring.gpg $i.sig; then
if ! patch -p0 < $i; then
echo "patch $i failed"
exit 1
fi
else
echo "patch $i has a bad signature!"
exit 2
fi
done
This is awesome, thanks.
Added auto-finding of latest patch level: https://gist.github.com/tonyflint/fddb5a3c669b8ae7d897
Thanks for the suggestions @Archetrix amd @TonyFlint. I have added downloading all available patches and put the bash version into env variables. I have also added tests for some of the subsequent bash vulnerabilities.
I'm still full of ideas :)
Is it intentionally to compile with default settings?
./configure --prefix=/usr --bindir=/bin --sbindir=/sbin --sysconfdir=/etc && make
Oh i just saw your tests at the end. I've got a test for the latest patch:
env ls="() { echo 'Game over'; }" bash -c ls
Basically if you get "ls" of your current folder it's OK if you get "Game over" you're screwed 😉
Or do this:
env date="() { echo 'doomsday'; }" bash -c date
If it returns a date it's ok if not .... 😄
I fun-tested bash 2.05b (has recent patches)
There are really old patches which don't have a .sig file.
thanks to all who helped putting this together, saves a lot of time!
btw.: Consider removing/archiving bash.old
Hi thanks for the script but im having problem with the last two tests..
dtest:/bash# bash --version/bash# echo $BASH_VERSION
GNU bash, version 3.2.54(1)-release (i686-pc-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.
dtest:
3.2.54(1)-release
dtest:/bash#/bash# bash -c 'true <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF' || echo "VULNERABLE to CVE-2014-7186"
dtest:
Segmentation fault
VULNERABLE to CVE-2014-7186
dtest:/bash# (for x in {1..200} ; do echo "for x$x in ; do :"; done; for x in {1..200} ; do echo done ; done) | bash || echo "VULNERABLE to CVE-2014-7187"/bash#
bash: line 129: syntax error near x129' bash: line 129:
for x129 in ; do :'
VULNERABLE to CVE-2014-7187
dtest:
@Archetrix, yes, I wanted to build in /usr/local/bin since this was a locally-compiled version of bash and not the one from the package.
@piccaso, no problem. i like keeping bash.old around in order to compare results of any new exploits found between the original and patched version.
@section1, previously the last two tests failed because bash 3.2 was not yet patched against them. however, a new patch was released on Oct 1, so you'll need to recompile bash. I can verify that the latest patch fixes the last two vulnerabilities.
Another …. tweak:
build bash 3.2, though this should work for other versions as well
BASH_VER=bash --version | grep 'version' | awk '{print $4};'
BASH_MAJOR=$(echo $BASH_VER | cut -d '.' -f1)
BASH_MINOR=$(echo $BASH_VER | cut -d '.' -f2)
Hi
I signed in here to comment THIS IMPORTANT ISSUE in your script (and forks as TonyFlint's).
The problem is the method to replace the vulnerable bash: a symbolic link to the patched bash. In my Debian 5 Lenny nodes, the /usr/local resides on A SEPARATE file system from the ROOT FILE SYSTEM, therefore /bin and /usr/local/bin reside on differente devices.
This causes an unbootable system because, in that case, the /bin/bash is not available to execute the scripts /etc/init.d/rcS, /etc/init.d/rc.
Therefore, instead of create a symbolic link, copy the patched binary bash into /bin.
Best regards
I added signature verification for the patches:
https://gist.github.com/href/54859127c183f67f947f