Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Shell Shock Exploitation Vectors (dfranke.us)
142 points by dfranke on Sept 27, 2014 | hide | past | favorite | 55 comments


On the theory that it is more likely to help HNers than the bad guys: http://httpd.apache.org/docs/2.2/mod/mod_ssl.html . Note in particular the part about StdEnvVars. The docs say it is off by default, but it is actually on in a lot of common deployment scenarios, for example if most of your apache configs were sourced from the big "apt-get install foo bar baz" line everyone copies from a blog post to get a working LAMP installation on an Ubuntu box.

I have not POCed this yet, but if I were trying to, I'd first try to make a client certificate with a highly non-standard Distinguished Name. It doesn't particularly matter if it fails validation as long as it doesn't fail in such a way that Apache dies before passing your information deeper into the guts of the web app.

After that point you're just looking for e.g. any page or library in the web app you can coerce to do a system() call or similar. While I was poking around in my own apps something like system(...) in Ruby on Ubuntu actually called /bin/sh rather than bash, but I think that is probably not the case for every combination of stack and distro.


Another thing that interested HNers can feel free to bird dog: PHP + Nginx is often deployed using fastcgi. (And, in my limited experience, far, far more likely to be deployed in greenfield development in the 2010s versus an actual CGI script. I think probably in excess of 20% of "technically savvy young software companies" I run this, the vast majority motivated by one ridiculously common piece of software that I'll refrain from naming because it suggests a trivial spray-and-pray for loop.)

fascgi_params puts a lot of attacker controlled data into "environment variables", but depending on php.ini's variables_order setting those might not actually go into what the rest of the word thinks is an environment variable (and hence not get passed to subprocesses, which is the point of the exercise). If php.ini's variables_order includes an "E", then the environment variable QUERY_STRING (among other things) will include attacker-chosen data. variables_order does include E by default, but does not in the php.ini which ships with the obvious apt-get commands for e.g. Ubuntu.


i wasnt able (yet) to exploit php-fpm, although i was able to sneak the user-agent into it and had an exploitable bash and a system() - call within this file

output -> https://gist.github.com/anonymous/ea60dc2915eccf0b803e

index.php -> https://gist.github.com/anonymous/883b989caba4156e47b6

but maybe suphp seems a little more suspicious?

/etc/suphp/suphp.conf ...

[handlers] ;Handler for php-scripts application/x-httpd-suphp="php:/usr/bin/php-cgi"

;Handler for CGI-scripts x-suphp-cgi="execute:!self"


I would like to reply to this but it is very hard to understand what you are alluding to. What is this software that one fifth of companies run and why is technically savvy in scare quotes, along with some veiled reference to something called spray-and-pray?

It's really impossible to understand you, but fastcgi_params does not put attacker controlled data into environment variables (without the quotes). That much is clear so normal usage of fastcgi is not in danger.


I will try being maximally explicit.

What is this software that one fifth of companies run

A ridiculously popular application, written in PHP, which is widely useful to software companies (among others).

why is technically savvy in scare quotes

I originally wrote "startup" then thought "Actually, this is deployed by a lot of people who aren't startups or who are only arguably startups, hmm, that is an unproductive debate, let's just say what I mean then move on."

some veiled reference to something called spray-and-pray?

Many applications have a well-known set of URLs associated with them. A spray-and-pray exploit is one which you can just fire at a well-known URL at every machine which responds to port 80 in IP4 space. The reason I am not identifying the vulnerable software written in PHP is that it would allow any script kiddie smart enough to text edit the existing exploit scripts to exploit that software as an additional vector.

fastcgi_params does not put attacker controlled data into environment variables (without the quotes)

I'm absolutely positive that fastcgi_params does indeed clobber $_ENV with attacker supplied data if PHP is configured as described above. I am less strongly confident that some configurations of PHP will allow $_ENV to get to at least some subprocesses. I am absolutely confident that some configurations of PHP will not allow you to set $_ENV nor set environmental variables. I have figured out ways to configure it which put the fastcgi_params in $_SERVER but not $_ENV and, separately, in $_ENV but not in environment variables passed to subprocesses. I'm aware of a PHP command which the documentation suggests defaults to passing $_ENV as actual environment variables to subprocesses but which I have not been able to verify actually works as the documentation says, due to it being 6 AM in the morning local time and me having insufficient motivation to continue finding more reasons to justify the conclusion that this bug is very, very bad news and bash needs to get patched immediately everywhere.


> I'm absolutely positive that fastcgi_params does indeed clobber $_ENV with attacker supplied data if PHP is configured as described above.

This is irrelevant. There is no known hole with global variables containing untrusted data.

> I am less strongly confident that some configurations of PHP will allow $_ENV to get to at least some subprocesses.

This could be relevant, if it is indeed passed in the environment.

However I can find no reference in the PHP documentation to this. That does not count for much, admittedly, and I am not very fluent in PHP. If this is real then it is a problem for many people so please share.

> I'm aware of a PHP command which the documentation suggests defaults to passing $_ENV as actual environment variables to subprocesses

Please spell it out already. I've been testing for the better part of two hours to find what you are alluding to, but I have no idea if I'm wasting my time or not.


> but fastcgi_params does not put attacker controlled data into environment variables

it does

https://gist.github.com/anonymous/ea60dc2915eccf0b803e


It looks like you have dumped the a PHP global variable, possibly $_ENV. Do you know of any circumstances where _ENV, or any other PHP variable with potentially untrusted data, is passed in environment variables?


i'm working on it it, but it looks like it works only under rare conditions


Sorry, are you saying Nginx+Fastcgi is vulnerable in general? I tested one of my boxes using nginx+fastcgi+mono and wasn't able to trigger the exploit. Or is it specifically nginx+fastcgi+php?


suphp, but only if your are stupid enough to switch safe_mode On

https://8ack.de/guides/suphp_shellshock


Re: /bin/sh versus /bin/bash (or similar) - note that many Linux systems link /bin/sh -> /bin/bash, so seeing /bin/sh, or knowing that's what system() calls, is not sufficient information on its own to determine your risk.


Yep. More broadly, I think the most sensible strategy for determining whether a system is at risk is "If it has bash and isn't airgapped assume that it's vulnerable because it is highly likely someone will find the vector you overlook."


Slightly more precisely: /bin/sh on ubuntu points to Dash, which is substantially more minimal than bash. Probably not chosen for security (I imagine speed was on their mind), but good either way.


In Debian /bin/sh points to dash too.


Always protect your OpenVPN instances with tls-auth, especially if your instance accepts connections from any IP. It prevents the SSL negotiation from even occurring if it doesn't match. It would have protected you from heart bleed, and it protects against shell shock.

There is no downside to using it. However, keep in mind that the key file is shared across all clients, so you probably want to change it periodically depending upon how much you trust your clients not to become hostile. You could run multiple server instances on different ports/IPs to subdivide your client base, or when rolling out a new key.


I wish the official OpenVPN howto [0] highlighted this sort of things a bit more.

As it is, it provides a clear and easy to follow path to a minimally viable setup, but only mentions many additional security parameters (tls-auth, running as unpriviledged user, chroot, increasing key size) under "Hardening OpenVPN Security", very far down the page, where people probably miss it. And this, even though some of these elements vastly increase the security with little to no downside.

[0] https://openvpn.net/index.php/open-source/documentation/howt...


Maybe a small note, but the variable needs to start with the bytes "() {", not the characters.

For example, () {̀ also triggers the parsing code. That's a ` over the { using Unicode.

FWIW, I haven't been able to actually exploit it this way, but referencing that variable in the new shell generates errors, so there might be something there:

bash: () {̀ :;}; echo vuln2: invalid variable name for name reference


One thing that'd be somewhat useful, with respect to #2 ("It must invoke bash"), is to separate it into those which specifically invoke bash, versus those that invoke /bin/sh. If bash is not installed as /bin/sh, as is the case on Debian and Ubuntu, do any of these (inetd, exim, etc.) still explicitly call it? Put differently, is this mainly an issue for distributions that ship bash as /bin/sh? Or do users of distributions like Debian also need to worry about common system services setting bash shell variables?

Maybe I'll try to answer that by pulling a bunch of Debian source packages and grepping for explicit calls to bash...


The one major one I found was the DHCP vulnerability; if you use ifupdown and configure and interface via DHCP, that uses dhclient, which invokes dhclient-script with attacker controlled variables. dhclient-script is explicitly written in bash, so is vulnerable.

I've tried doing explicit grepping for bash throughout various source code, but it's a lot of work to then trace back if that particular script is ever executed by some chain of commands that ultimately originated from something networked which sets environment variables to attacker controlled values.


Even if they don't explicitly invoke bash, it's possible that they call a program which calls a program which invokes a bash script somewhere.

Debian switched /bin/sh to link to dash a while back, but some maintainers decided to simply change the #!/bin/sh at the top of the shell scripts in their packages to #!/bin/bash rather than remove the bashisms. dhclient is the worst offender in the current kerfuffle, but I'm sure there are others.


They did switch /bin/sh to dash, which is why it seems to me that grepping for "bash" would be quite effective.


For Mac OS X, until Apple releases a software update, I've applied the original CVE-2014-6271 (shellshock) patch and the CVE-2014-7169 patch. Repository and instructions to reproduce without trusting me are located here: https://github.com/ido/macosx-bash-92-shellshock-patched

Binary releases are here: https://github.com/ido/macosx-bash-92-shellshock-patched/rel... ...including a .pkg file that can be installed with a double-click.

Instruction here: https://github.com/ido/macosx-bash-92-shellshock-patched/blo...


This appears (to me) to be another good temporary fix for OS X:

http://apple.stackexchange.com/a/146851

It provides a one-step copy and paste into the terminal to download, patch and compile bash from apple.com and gnu.org.


You missed one of the big ones, DHCP. dhclient calls dhclient-script with attacker controlled environment variables, and on several Linux distros I checked, dhclient-script explicitly uses Bash, so even Debian and Ubuntu, which use dash as sh, are vulnerable.


Someone else already pointed this out in my comments section. I'm working on an update.


rather than adding fixup to these (which arent all exactly directly exploitable, and sometimes have dodgy POCs), it'd be nice if we stopped calling the shell at all and when necessary, always wipe the env entirely and parse the user input by allowing a specific white list.

these methods were used a decade ago and programs not doing stuff like clearing the env were seen as poorly made programs in need of rewrite. Unfortunately that has changed.


Thank you for mentioning this. What I don't understand is that no one is talking about the responsibility of the programs reading the user input. They have a responsibility to validate anything they receive using a whitelisting approach (i.e. denying anything that doesn't match expected patterns).

If a program simply slurps in user input without doing any basic validation according to published RFCs then there's a bug in that program.


I wonder if anyone has thought of any indirect vectors? Imagine a Windows based virus that can scan a private network and use the shellshock exploit to infect never-before-seen unix devices with a HTTP service?


So assuming it's an online EC2 server not-updated LAMP stack with an empty cgi folder and a lone html page with hello world. Is that vulnerable to bash exploitation in any way?


Probably not, unless there's something really weird in your Apache config.


I feel like the only reasonable thing to do now is to capture all traffic going to a web server and analyze every field for that's that eventually become env vars.


Or fix the shell or use another one.


This of course assumes that bash is set as the default shell for those users all those programs run under. None of my systems have bash installed, thus they aren't vulnerable. FreeBSD by default does not ship with bash, and unless it is specifically installed for 3rd party software use, it is not required for anything, and certainly won't be found as /bin/sh...

Shell shock is being blown out of proportion, people are worried local machines they use to browse internet are going to get popped when in reality it is only really Linux machines that have bash as the default shell that should be worried.


Any program that calls a library that calls a program that executes a script with #!/bin/bash could be vulnerable, client or server. There are many ways data can get into an environment variable.

For example, a hypothetical encryption library might be a wrapper around /usr/bin/gpg or /usr/bin/openssl, and to avoid having arguments show up in ps or top, it might pass arguments as environment variables. Later a secure e-mail program might use that library to validate a signature from an e-mail, and pass signature data in an environment variable. So that's MacOSX and Fedora owned with /bin/bash as /bin/sh. Say the encryption library used a script written in Bash to do some other processing. That's BSD owned.


Except that bash is not installed by default... if bash is not installed how does BSD suddenly become vulnerable?


This is as helpful as a windows admin saying 'this whole thing seems to be blown out of proportion, none of my servers are vulnerable'.


It would have been installed as a dependency of whatever used it in some obscure way.


Okay, since someone actually downvoted both of my comments, I'll point out that libgpgme is a common encryption library that calls /usr/bin/gpg. Fortunately it uses execv(), but that leaves the environment unchanged so if anything further down the chain uses Bash it's still vulnerable.

I'll also provide a list of files from /usr/bin that are actually implemented using Bash (from a Linux Mint system). Anything using these with user-controlled environment variable values is vulnerable:

    $ grep -nR '#!.*bash' * | grep :1:
    apg:1:#!/bin/bash
    aptitude-create-state-bundle:1:#!/bin/bash
    aptitude-run-state-bundle:1:#!/bin/bash
    banshee:1:#!/usr/bin/env bash
    cautious-launcher:1:#!/bin/bash
    checkinstall:1:#!/bin/bash
    cinnamon2d:1:#!/bin/bash
    dns-fix:1:#!/bin/bash
    editdiff:1:#!/bin/bash
    fakenect:1:#!/bin/bash
    fakeroot:1:#!/bin/bash
    fakeroot-sysv:1:#!/bin/bash
    fakeroot-tcp:1:#!/bin/bash
    gnome-www-browser:1:#!/bin/bash
    google-chrome:1:#!/bin/bash
    google-chrome-stable:1:#!/bin/bash
    gufw-pkexec:1:#!/bin/bash
    im-config:1:#!/bin/bash -e
    init-checkconf:1:#!/bin/bash
    installwatch:1:#!/bin/bash
    inxi:1:#!/bin/bash
    itweb-settings:1:#!/bin/bash
    javaws:1:#!/bin/bash
    lcf:1:#!/bin/bash
    ldd:1:#! /bin/bash
    libtool:1:#! /bin/bash
    lua2dox_filter:1:#!/bin/bash
    lzcmp:1:#!/bin/bash
    lzdiff:1:#!/bin/bash
    lzegrep:1:#!/bin/bash
    lzfgrep:1:#!/bin/bash
    lzgrep:1:#!/bin/bash
    lzless:1:#!/bin/bash
    lzmore:1:#!/bin/bash
    mate-help:1:#!/bin/bash
    mintBackup:1:#!/bin/bash
    mint-fortune:1:#!/bin/bash
    mintupload:1:#!/bin/bash
    mintupload-manager:1:#!/bin/bash
    muinshee:1:#!/usr/bin/env bash
    mysqld_safe:1:#!/bin/bash
    p7zip:1:#!/bin/bash
    pipelight-plugin:1:#!/usr/bin/env bash
    pnmindex:1:#!/bin/bash
    policyeditor:1:#!/bin/bash
    ppmquantall:1:#!/bin/bash
    rarian-sk-config:1:#!/bin/bash
    rarian-sk-extract:1:#!/bin/bash
    rarian-sk-rebuild:1:#!/bin/bash
    rarian-sk-update:1:#!/bin/bash
    scrollkeeper-config:1:#!/bin/bash
    scrollkeeper-extract:1:#!/bin/bash
    scrollkeeper-rebuilddb:1:#!/bin/bash
    scrollkeeper-update:1:#!/bin/bash
    sotruss:1:#! /bin/bash
    steam:1:#!/usr/bin/env bash
    su-to-root:1:#!/bin/bash
    tomboy:1:#!/usr/bin/env bash
    tzselect:1:#!/bin/bash
    ucf:1:#!/bin/bash
    ucfr:1:#! /bin/bash
    usb-devices:1:#!/bin/bash
    X11/scrollkeeper-config:1:#!/bin/bash
    X11/fakenect:1:#!/bin/bash
    X11/lzgrep:1:#!/bin/bash
    X11/cautious-launcher:1:#!/bin/bash
    X11/xzdiff:1:#!/bin/bash
    X11/aptitude-create-state-bundle:1:#!/bin/bash
    X11/mint-fortune:1:#!/bin/bash
    X11/mate-help:1:#!/bin/bash
    X11/scrollkeeper-extract:1:#!/bin/bash
    X11/fakeroot:1:#!/bin/bash
    X11/editdiff:1:#!/bin/bash
    X11/lzdiff:1:#!/bin/bash
    X11/apg:1:#!/bin/bash
    X11/mintupload-manager:1:#!/bin/bash
    X11/gnome-www-browser:1:#!/bin/bash
    X11/ucfr:1:#! /bin/bash
    X11/lzcmp:1:#!/bin/bash
    X11/libtool:1:#! /bin/bash
    X11/im-config:1:#!/bin/bash -e
    X11/xzmore:1:#!/bin/bash
    X11/mintupload:1:#!/bin/bash
    X11/xzegrep:1:#!/bin/bash
    X11/javaws:1:#!/bin/bash
    X11/xchat-systray:1:#!/bin/bash
    X11/itweb-settings:1:#!/bin/bash
    X11/dns-fix:1:#!/bin/bash
    X11/su-to-root:1:#!/bin/bash
    X11/checkinstall:1:#!/bin/bash
    X11/usb-devices:1:#!/bin/bash
    X11/rarian-sk-extract:1:#!/bin/bash
    X11/tzselect:1:#!/bin/bash
    X11/google-chrome-stable:1:#!/bin/bash
    X11/xzcmp:1:#!/bin/bash
    X11/xzgrep:1:#!/bin/bash
    X11/pipelight-plugin:1:#!/usr/bin/env bash
    X11/lcf:1:#!/bin/bash
    X11/scrollkeeper-rebuilddb:1:#!/bin/bash
    X11/banshee:1:#!/usr/bin/env bash
    X11/cinnamon2d:1:#!/bin/bash
    X11/xzfgrep:1:#!/bin/bash
    X11/muinshee:1:#!/usr/bin/env bash
    X11/lzfgrep:1:#!/bin/bash
    X11/mintBackup:1:#!/bin/bash
    X11/tomboy:1:#!/usr/bin/env bash
    X11/fakeroot-sysv:1:#!/bin/bash
    X11/aptitude-run-state-bundle:1:#!/bin/bash
    X11/gufw-pkexec:1:#!/bin/bash
    X11/init-checkconf:1:#!/bin/bash
    X11/x-www-browser:1:#!/bin/bash
    X11/lzegrep:1:#!/bin/bash
    X11/rarian-sk-update:1:#!/bin/bash
    X11/sotruss:1:#! /bin/bash
    X11/ldd:1:#! /bin/bash
    X11/ppmquantall:1:#!/bin/bash
    X11/rarian-sk-rebuild:1:#!/bin/bash
    X11/xzless:1:#!/bin/bash
    X11/rarian-sk-config:1:#!/bin/bash
    X11/p7zip:1:#!/bin/bash
    X11/google-chrome:1:#!/bin/bash
    X11/lzmore:1:#!/bin/bash
    X11/fakeroot-tcp:1:#!/bin/bash
    X11/mysqld_safe:1:#!/bin/bash
    X11/ucf:1:#!/bin/bash
    X11/policyeditor:1:#!/bin/bash
    X11/lzless:1:#!/bin/bash
    X11/lua2dox_filter:1:#!/bin/bash
    X11/installwatch:1:#!/bin/bash
    X11/inxi:1:#!/bin/bash
    X11/scrollkeeper-update:1:#!/bin/bash
    X11/steam:1:#!/usr/bin/env bash
    X11/pnmindex:1:#!/bin/bash
    xchat-systray:1:#!/bin/bash
    x-www-browser:1:#!/bin/bash
    xzcmp:1:#!/bin/bash
    xzdiff:1:#!/bin/bash
    xzegrep:1:#!/bin/bash
    xzfgrep:1:#!/bin/bash
    xzgrep:1:#!/bin/bash
    xzless:1:#!/bin/bash
    xzmore:1:#!/bin/bash


And before you believe that your Linux box is any indication of how common a dependency bash is...

I just grepped all the Makefiles in my ports tree for 'shells/bash', and came up with 48 matches. This includes ports that depend on bash at build time, at test time, and at runtime. So for people who just use packages, the number of things that are going to pull in bash (as a runtime dep) is lower than that.

We have many of the same programs you have, but they do not use bash. For example, all your executables that start with xz or lz. I have them, most of them anyway, but they use /bin/sh, not /bin/bash.

I use BSD on the desktop, and out of the three hundred packages I have installed, none have pulled bash in as a dep. I don't have bash, I haven't had it for years.


There is a couple more ports out there that require it for run, but the numbers are quite low considering the amount of software that is available in the ports tree:

http://www.freshports.org/shells/bash


My numbers are from the OpenBSD ports tree.


That's a desktop. Come back when you've audited the popcon top 100.


That's a goalpost. Come back when it's not moving.


All those osx machines have bash as /bin/sh by default too.

It's unclear how often shellouts happen within OSX for various operations.


https://access.redhat.com/articles/1200223

CUPS probably too, but no POC seen yet


I've got an old red hat somewhere, without yum and apt-get, what can I do to update bash on there? (RHEL3).


I've posted what I did (as best as I can recall) here: https://gist.github.com/anonymous/56afdedbf92ea98ba237

It's entirely possible I forgot something. I haven't built an RPM in years and didn't do it often in the first place. I almost didn't bother now except I can't entirely exclude the possibility that two RHEL3 servers that aren't going anywhere might have an attack vector hidden in them somewhere.

Edit: Changed link to fixed gist.


If that version is no longer supported by RedHat, you can compile the patched bash yourself, but you should really try to upgrade as there are probably other vulnerabilities in other components.


suphp might be exploitet, but only with stupid settings

https://8ack.de/guides/suphp_shellshock


Somewhat ironic for all the noise made about qmail that many configurations of it are vulnerable. I wonder if Bernstein will be paying out that $1000 reward, and if so, to who

See section 1.3:

http://cr.yp.to/qmail/qmailsec-20071101.pdf


The qmail bounty explicitly disclaims "bugs outside of qmail", which this one clearly is. So, no.


Why it's not exploitable without the shellshock-vulnerable bash, you could argue that qmail is not validating the input in accordance with the RFCs. In fact, that's one of the things I said here: http://marc.info/?l=qmail&m=141183309314366&w=2


Input validation is an orthogonal issue here, since bash doesn't know anything about RFC821/RFC2821, doesn't expect data in that format, and doesn't make any guarantees about what it will or won't do on such data.

The only reasonable policy for a shell to follow is to be entirely input-agnostic and never execute code based on the contents of an environment variable (regardless of which RFCs the contents conform to).


Of course bash doesn't know and shouldn't know about the SMTP RFCs. Yes, bash shouldn't execute code in variables. I was talking about input validation in qmail itself, not bash.

Even though bash shouldn't have executed the code, better input validation and RFC conformance in qmail could have prevented exploitation of bash. You know, defense-in-depth.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: