Mitigating the shellshock vulnerability (CVE-2014-6271 and CVE-2014-7169)

Updated -

Warning

These mitigations involve making changes that could lead to unintended consequences if they are not performed correctly. It is recommended that only experienced system administrators who fully understand the implications of these changes apply the mitigations documented in this article. These mitigations have only been subjected to limited testing by Red Hat.

Important: Given that package updates are available to correct the flaws these mitigations were provided for, these mitigations should only be used in exceptional circumstances and not as a replacement for installing the updated packages. Red Hat recommends all users of Bash to upgrade to the updated packages as swiftly as possible.

Network-based mitigations

Network mitigation 1: mod_security rules

The following mod_security rules can be used to reject HTTP requests containing data that may be interpreted by Bash as a function definition if set in its environment. They can be used to block attacks against web services, such as attacks against CGI applications.
Request Header values:

SecRule REQUEST_HEADERS "^\(\s*\)\s+{" "phase:1,deny,id:1000000,t:urlDecode,status:400,log,msg:'CVE-2014-6271 - Bash Attack'"

SERVER_PROTOCOL values:

SecRule REQUEST_LINE "^\(\s*\)\s+{" "phase:1,deny,id:1000001,status:400,log,msg:'CVE-2014-6271 - Bash Attack'"

GET/POST names:

SecRule ARGS_NAMES "^\(\s*\)\s+{" "phase:2,deny,id:1000002,t:urlDecode,t:urlDecodeUni,status:400,log,msg:'CVE-2014-6271 - Bash Attack'"

GET/POST values:

SecRule ARGS "^\(\s*\)\s+{" "phase:2,deny,id:1000003,t:urlDecode,t:urlDecodeUni,status:400,log,msg:'CVE-2014-6271 - Bash Attack'"

File names for uploads:

SecRule FILES_NAMES "^\(\s*\)\s+{"  "phase:2,deny,id:1000004,t:urlDecode,t:urlDecodeUni,status:400,log,msg:'CVE-2014-6271  - Bash Attack'"

It is possible, however unlikely, that these rules may result in false positives. These false positives, along with actual attempts, could result in log files of significant size.

Network mitigation 2: IPTables rules

It is possible to use IPTables string matching to attempt to drop packets that could be part of an attack, using:

# iptables -A INPUT -m string --algo bm --hex-string '|28 29 20 7B|' -j DROP
# ip6tables -A INPUT -m string --algo bm --hex-string '|28 29 20 7B|' -j DROP

Note that this is a weak workaround, as an attacker could easily send one or two characters per packet, which would avoid matching this signature check. It may, in conjunction with logging, provide an overview of automated attempts at exploiting this vulnerability.

System-based mitigations

The shellshock vulnerability arises from the fact that you can create environment variables with specially-crafted values before calling the Bash shell. These variables can contain code, which gets executed as soon as the shell is invoked. The initial patch for CVE-2014-6271 was found to be incomplete. The patch for CVE-2014-7169 addresses this, but it does not entirely remove the vulnerable functionality. If you entirely remove the vulnerable functionality from Bash, all possible attack variants will be mitigated.

System-based mitigation 1: LD_PRELOAD

LD_PRELOAD is an environment variable used by the runtime linking process by searching for shared libraries at alternate locations and by forcibly loading and linking libraries that would be used. This forces some symbols/functions to be loaded and prioritized over built in functions a program. This code creates a new function "strip_env" with the gcc "constructor" attribute set. Functions with this attribute set will execute before entering main(). See https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html for more details.

$ sha256sum bash_ld_preload.c
28cb0ab767a95dc2f50a515106f6a9be0f4167f9e5dbc47db9b7788798eef153 
bash_ld_preload.c
  • Compile it:
$ gcc bash_ld_preload.c -fPIC -shared -Wl,-soname,bash_ld_preload.so.1 \
-o bash_ld_preload.so
  • Copy bash_ld_preload.so to /lib:
# cp bash_ld_preload.so /lib/

If you wish to apply this workaround across the entire system:

  • Add the following to /etc/ld.so.preload on a line by itself:
/lib/bash_ld_preload.so
  • Restart all relevant services or reboot the system.

Note that this is potentially very dangerous. It is recommend that you just apply this workaround to specific services that may be exploitable on your system. This can be achieved by adding bash_ld_preload.so to the LD_PRELOAD environment variable in the script that will initialize the service. However, this will not work for services that use SUID binaries in some capacity (e.g. httpd with SUEXEC), as SUID binaries will not honour the LD_PRELOAD command.

  • Add the following two lines at the top of /etc/init.d/httpd, after the shebang line:
LD_PRELOAD=/lib/bash_ld_preload.so
export LD_PRELOAD
  • Edit httpd.conf and add the following directive and save the configuration file:
PassEnv LD_PRELOAD
  • Then restart httpd:
# service httpd restart

System-based mitigation 2: systemtap

It may be possible to mitigate by enforcing bash to use privileged mode.

install the bash debuginfo

$ sudo debuginfo-install bash

install systemtap

$ sudo yum install systemtap

Run this command:

$ nohup sudo stap -g -e '  probe process("/bin/bash").function("initialize_shell_variables") { $privmode=1 }  '

This ensures that the bash privileged mode (the equivalent of bash -p) is always enabled. To verify, test for the original vulnerability (CVE-2014-6271):

$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
this is a test

The above is an example when it is NOT affected. Finally, test for the new vulnerability (CVE-2014-7169):

$  env X='() { (a)=>\' sh -c "echo date"; cat echo
date
cat: echo: No such file or directory

The above is an example when it is NOT affected.

Force-enabling privileged mode has side effects that some system administrators may need to be aware of. Listed below is a relevant extract from the bash man page.

  -p  Turn on privileged mode.  In this mode, the $ENV and $BASH_ENV files
      are not processed, shell functions are not inherited from the
      environment, and the SHELLOPTS, BASHOPTS, CDPATH, and GLOBIGNORE
      variables, if they appear in the environment, are ignored.  If the
      shell is started with the effective user (group) id not equal to the
      real user (group) id, and the -p option is not supplied, these
      actions are taken and the effective user id is set to the real user
      id.  If the -p option is supplied at startup, the effective user id
      is not reset.  Turning this option off causes the effective user and
      group ids to be set to the real user and group ids.

This script above is a temporary mitigation and will not persist between reboots.

12 Comments

RPM package for this vulnerability.

The first rule has:
SecRule REQUEST_HEADERS ^(\s*)\s+{" "phase:1,deny,id:1000000,t:urlDecode,status:400,log,msg:'CVE-2014-6271 - Bash Attack'"

It is missing a double quote in the regular expression. So it should be:
SecRule REQUEST_HEADERS "^(\s*)\s+{" "phase:1,deny,id:1000000,t:urlDecode,status:400,log,msg:'CVE-2014-6271 - Bash Attack'"

If you just copy/paste it into your mod_sec rules it isn't going to work.

Thanks very much for pointing this out, David. This has now been fixed.

silly refresh on page ignore this

The "Compile it" instructions would probably benefit from having a continuation character at the end of the first line, or including bash_ld_preload.so on the first line.

Thanks Barry, I have now made this change.

The bash_ld_preload.c appears to work for CVE-2014-6271 and CVE-2014-7169 as is indicated in this article, so it does work to fix the issues that it claims to fix. I have just tested this against CVE-2014-7186 and CVE-2014-7187, and it does not appear to address these vulnerabilities. Are there plans to offer an updated bash_ld_preload.c that addresses these?

Hello Barry,

Can you share with us how you are testing bash?

The bash_ld_preload.c addresses situations where the attackers are able to cause bash to parse environment strings via the () { syntax, it is not designed to detect testing of the vulnerabilities of local bash -c "test commands here".

Detecting and mitigating the environment string parsing will block network attack avenues, where an attacker is able to control the environment strings being set via common avenues such as HTTP CGI binaries, etc.

If you are able to share your techniques for testing, we'll be sure to update the bash_ld_preload.c code if appropriate for the aims we have of it.

Thanks,
Andrew Griffiths

Andrew,

These tests are from http://shellshocker.net/. I am making the assumption that these are valid tests for the corresponding CVEs. The second test does use bash -c so it may not be what you are looking to fix.

Thanks,
Barry

CVE-2014-7186

$ bash -c 'true <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF' || echo "CVE-2014-7186 vulnerable, redir_stack"
Segmentation fault

CVE-2014-7186 vulnerable, redir_stack

CVE-2014-7187:

$ (for x in {1..200} ; do echo "for x$x in ; do :"; done; for x in {1..200} ; do echo done ; done) | bash || echo "CVE-2014-7187 vulnerable, word_lineno"
bash: line 129: syntax error near x129'
bash: line 129:
for x129 in ; do :'
CVE-2014-7187 vulnerable, word_lineno

Barry,

Those tests are valid, but they're not reachable via standard network means (for example, X-ShellShock: code here and hitting a /cgi-bin/ script, etc.).

To make them reachable via the network, you need to get bash to parse those strings, where is where the function declarations come into effect to make it trigger those vulnerabilities.

This is where the bash_ld_preload.c comes into effect - it blocks attacks by preventing the use of function declarations in the environment variables, which prevents network based attacks.

Does that clear up the purposes and design goals of the bash_ld_preload.c?

Andrew - Yes it does. Thank you for your explanation.

So without using yum, there is zero RPM package for this CVe vulnerability series ?
https://twitter.com/JAaronAnderson/status/520204664718258177

I suppose Ill try bash-3.2-33.el5_11.4.i386.rpm & rerun detector.
will this rpm atleast help ? on the right track ?