75

I did apt-get update; apt-get upgrade -y on all systems I'm running. I'm not sure if my /etc/apt/sources.list is good enough on all of these systems. I would like to quickly check each system again, ideally with a one-line shell command.

Does such a one-line shell command exist and if so, what is it?

Note this question is mainly about CVE-2014-6271.

  • 1
    bash --version The bug effects versions of bash up to and including 4.3 – RoraΖ Sep 25 '14 at 11:31
  • 18
    @raz Checking the bash version is useless (except that versions after 4.3, which do not exist yet, won't be affected). Most systems will fix the hole by patching just the hole (usually by applying their distribution's normal update process), not by upgrading to a whole new version of bash (which, again, does not exist yet). – Gilles Sep 25 '14 at 11:43
  • @Gilles bash --version will report a version number like 4.3.25 (which is the the patch which fixes the initial, although not the full, Shell Shock vulnerability). There's no reason to think that a patch- level release is any less able to fully patch the problem than some future 4.4 version. – chepner Sep 28 '14 at 13:37
  • @chepner ... which is exactly why checking the version number is useless. On most distributions, the upgrade that fixes the hole doesn't change the version number. The vulnerable version and the fixed version have the same version number. You cannot use it to tell whether the vulnerability is present. – Gilles Sep 28 '14 at 14:14
  • 2
    I'd be a little miffed if my distribution is patching the code without bumping the version number at all. – chepner Sep 28 '14 at 15:05
121

Is my bash vulnerable?

This simple command is a sufficient test to see if your version of bash is vulnerable:

x='() { :;}; echo VULNERABLE' bash -c :

It's not necessary to have extra text printed to signify that the command has actually run, because patched versions of bash will report a warning when a variable in its starting environment contains exploit code for the patched vulnerability.

On a vulnerable system:

$ x='() { :;}; echo VULNERABLE' bash -c :
VULNERABLE

On a patched system:

$ x='() { :;}; echo VULNERABLE' bash -c :
bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x'

For a detailed explanation of what this does and does not test for, and why, see "Other Function Parsing Bugs" below.

Is my system vulnerable?

If your bash isn't vulnerable then your system isn't vulnerable.

If your bash is vulnerable, then your system is vulnerable inasmuch as it uses bash along attack vectors such as CGI scripts, DHCP clients and restricted SSH accounts. Check whether /bin/sh is bash or some other shell. The vulnerability is in a bash-specific feature and other shells such as dash and ksh are not affected. You can test the default shell by running the same test as above with sh instead of bash:

x='() { :;}; echo VULNERABLE' sh -c :
  • If you see an error message, then your system has a patched bash and isn't vulnerable.
  • If you see VULNERABLE, then your system's default shell is bash and all attack vectors are a concern.
  • If you see no output, then your system's default shell is not bash, and only parts of your system that use bash are vulnerable. Check for:
    • Scripts executed by bash (starting with #!/bin/bash, not #!/bin/sh) from CGI or by a DHCP client.
    • Restricted SSH accounts whose shell is bash.

How This Test Works

It runs the command bash -c : with the literal text () { :;}; echo VULNERABLE set as the value of the environment variable x.

  • The : builtin performs no action; it's used here where a non-empty command is required.

  • bash -c : creates an instance of bash that runs : and exits.

    Even this is sufficient to allow the vulnerability to be triggered. Even though bash is being invoked to run only one command (and that command is a no-op), it still reads its environment and interprets each variable whose contents start with () { as a function (at least those whose names are valid function names) and runs it so the function will be defined.

    The intent behind this behavior of bash is to run only a function definition, which makes a function available for use but doesn't actually run the code inside it.

  • () { :;} is the definition for a function that performs no action when called. A space is required after { so that { is parsed as a separate token. A ; or newline is required before } for it to be accepted as correct syntax.

    See 3.3 Shell Functions in the Bash Reference Manual for more information on the syntax for defining shell functions in bash. But note that the syntax used (and recognized) by bash as a valid exported shell function whose definition it should run is more restrictive:

    1. It must start with the exact string () {, with exactly one space between ) and {.
    2. And while shell functions occasionally have their compound statement enclosed in ( ) instead of { }, they are still exported inside { } syntax. Variables whose contents start with () ( instead of () { will not test for or otherwise trigger the vulnerability.
  • bash should stop executing code after the closing }. But (unless patched) it doesn't! This is the wrong behavior that constitutes CVE-2014-6271 ("Shellshock").

    ; ends the statement that defines the function, allowing subsequent text to be read and run as a separate command. And the text after ; doesn't have to be another function definition--it can be anything at all.

  • In this test, the command after ; is echo VULNERABLE. The leading space before echo does nothing and is present just for readability. The echo command writes text to standard output. The full behavior of echo is actually somewhat complicated, but that's unimportant here: echo VULNERABLE is simple. It displays the text VULNERABLE.

    Since echo VULNERABLE is only run if bash is unpatched and running code after function definitions in environment variables, this (and many other tests similar to it) is an effective test of whether or not the installed bash is vulnerable to CVE-2014-6271.


Other Function Parsing Bugs (and why that test and those like it don't check for them)

The patch that has been released as of this writing, and the commands described and explained above for checking vulnerability, apply to the very severe bug known as CVE-2014-6271. Neither this patch nor the commands described above for checking vulnerability apply to the related bug CVE-2014-7169 (nor should they be assumed to apply to any other bugs that may not yet have been discovered or disclosed).

The bug CVE-2014-6271 arose from a combination of two problems:

  1. bash accepts function definitions in arbitrary environment variables, and
  2. while doing so, bash continues running any code that exists after the closing brace (}) of a function definition.

As of this writing, the existing fix for CVE-2014-6271 that has been released (and rolled out by many downstream vendors)--that is, the fix you'd get by updating your system or by applying the existing patch manually--is a fix for 2.

But in the presence of other mistakes in bash's code, 1 is potentially a source of many additional parsing bugs. And we know at least one other such bug exists--specifically, CVE-2014-7169.

The command presented in this answer tests for whether or not an installed bash is patched with the existing (i.e., first official) fix for CVE-2014-6271. It tests vulnerability to that specific parsing bug: "GNU Bash through 4.3 processes trailing strings after function definitions in the values of environment variables[...]"

That specific bug is extremely severe--and the available patch does fix it--while CVE-2014-7169 appears to be less severe but is definitely still cause for concern.

As Stéphane Chazelas (discoverer of the Shellshock bug) has recently explained in an answer to When was the shellshock (CVE-2014-6271) bug introduced, and what is the patch that fully fixes it? on Unix.SE:

There is a patch that prevents bash from interpreting anything else than the function definition in there (https://lists.gnu.org/archive/html/bug-bash/2014-09/msg00081.html), and that's the one that has been applied in all the security updates from the various Linux distributions.

However, bash still interprets the code in there and any bug in the interpreter could be exploited. One such bug has already been found (CVE-2014-7169) though its impact is a lot smaller. So there will be another patch coming soon.


But if that's what the exploit looks like...

Some people, here and elsewhere, have asked why x='() { :;}; echo VULNERABLE' bash -c : printing VULNERABLE (or similar) should be considered alarming. And I've recently seen the misconception circulating that because you have to have interactive shell access already to type in that particular command and press enter, Shellshock must somehow not be a serious vulnerability.

Although some of the sentiments I've heard expressed--that we should not rush to panic, that desktop users behind NAT routers shouldn't put their lives on hold to build bash from source code--are quite correct, confusing the vulnerability itself with the ability to test for it by running some specific command (such as the command presented here) is a serious mistake.

The command given in this post is an answer to the question, "Is there a short command to test if my server is secure against the shellshock bash bug?" It is not an answer to "What does shellshock look like when it's used against me by a real attacker?" and it is not an answer to the question, "What does someone have to do to successfully exploit this bug?" (And it is also not an answer to, "Is there a simple command to infer from all technical and social factors if I'm personally at high risk?")

That command is a test, to see if bash will execute code written, in a particular way, in arbitrary environment variables. The Shellshock vulnerability is not x='() { :;}; echo VULNERABLE' bash -c :. Instead, that command (and others like it) is a diagnostic to help determine if one is affected by Shellshock.

  • Shellshock has wide ranging consequences, though it is true that the risk is almost certainly less for desktop users who are not running remotely accessible network servers. (How much less is something I don't think we know at this point.)
  • In contrast, the command x='() { :;}; echo VULNERABLE' bash -c : is entirely inconsequential except insofar as it is useful for testing for Shellshock (specifically, for CVE-2014-6271).

For those who are interested, here are a few resources with information on why this bug is considered severe and why environment variables, particularly on network servers, may contain untrusted data capable of exploiting the bug and causing harm:

To further illustrate the conceptual distinction here, consider two hypotheticals:

  1. Imagine if instead of suggesting x='() { :;}; echo VULNERABLE' bash -c : as the test, I had suggested bash --version as the test. (That would actually not be particularly appropriate, because OS vendors frequently backport security patches to older versions of software. The version information a program gives you can, on some systems, make it look like the program would be vulnerable, when actually it has been patched.)

    If testing by running bash --version were being suggested, no one would say, "But attackers can't sit at my computer and type bash --version, so I must be fine!" This is the distinction between a test and the problem being tested for.

  2. Imagine if an advisory were issued suggesting that your car might have some safety problem, such as airbag failure or bursting into flames in a collision, and that factory demonstrations had been streamed. No one would say, "But I would never accidentally drive or tow my car 900 miles to the factory and have it loaded with an expensive crash dummy and slammed into a concrete wall. So I must be fine!" This is the distinction between a test and the problem being tested for.

  • 10
    Hmm, but if I can run bash then can't I already execute arbitrary commands on a system? How is this a vulnerability? – Ajedi32 Sep 25 '14 at 14:08
  • 9
    @Ajedi32 x='() { :;}; echo VULNERABLE' bash -c : is a test to see if your bash is patched. The reason CVE-2014-6271 is a vuln at all is it gives the power to run arbitrary commands to anyone who can set the value of some environment variable (under conditions when a bash will then run with that variable set). Environment variables are commonly used to pass unsanitized, user-supplied data between processes. For example, this is often exploitable via HTTP. See seclists.org/oss-sec/2014/q3/650 under "So far, HTTP requests to CGI scripts have been identified as the major attack vector." – Eliah Kagan Sep 25 '14 at 14:31
  • 2
    @JakeGould The worst thing about this vulnerability is that to exploit it you don't need to have an account at all. Even if (for example) your web server runs under a strictly limited user account, it would be very bad for an attacker to be able to run arbitrary commands as that limited user, completely controlling your web server (and more). See the explanation here. The most convenient ways to test for a vulnerability are not always of the same form as the most devastating ways to exploit it in the wild. – Eliah Kagan Sep 25 '14 at 15:36
  • 10
    @JakeGould There's no one program that's "the standard Unix shell." Different OSes uses different shells for /bin/sh. On GNU/Linux sh is usually a link to, or copy of, some other shell. In Ubuntu and Debian, dash provides sh, though bash did in years past. On some OSes, sh remains bash. (I believe Slackware is an example, though I haven't used it recently.) A quick web search, or Wikipedia, would have saved you from your misconception and saved me from your false accusation of ignorance. – Eliah Kagan Sep 25 '14 at 17:12
  • 6
    @user53029 The released fix for CVE-2014-6271 doesn't fix the underlying design flaw that makes it so bash must parse function definitions from the environment just right or suffer potential security bugs. In that sense the fix is incomplete. But it does (as far as is known) completely fix the bug of executing trailing code after a function definition. So it largely makes sense to consider CVE-2014-7169 a separate vulnerability. The patch for 6271 and the test in this answer for determining if that patch is effectively applied do not test for 7169. I've expanded this answer with details. – Eliah Kagan Sep 25 '14 at 20:07
12

You can check if you're vulnerable by running the following lines in your default shell, which on many systems will be Bash. If you see the words "busted", then you're at risk. If only the second command prints “busted”, then your bash is vulnerable, but the vulnerability only impacts the parts of your system that invoke bash explicitly, not the parts that run the default shell (sh). If neither command prints “busted” then your system is patched.

env X="() { :;} ; echo busted" /bin/sh -c "echo completed"
env X="() { :;} ; echo busted" bash -c "echo completed"

Source

After patching, your system may still be vulnerable:

env X='() { (a)=>\' bash -c "echo echo vuln"; [[ "$(cat echo)" == "vuln" ]] && echo "still vulnerable :("

Source and another source

  • 3
    I'm not sure what `which bash` is supposed to accomplish that bash wouldn't: both run whichever bash appears first in PATH, and it's not as though env needs fully qualified names. (Also, you don't need env at all for this.) – Eliah Kagan Sep 25 '14 at 12:41
  • 1
    @BadSkillz, can you add some clarification to env X='() { (a)=>\' sh -c "echo date"; cat echo? What is that supposed to do or show me? – guaka Sep 25 '14 at 13:18
  • 1
    @Eliah, it'd be great if you can come up with a better answer. – guaka Sep 25 '14 at 13:18
  • which bash might get you past a sanitized input restricting shell command path literals. – zedman9991 Sep 25 '14 at 13:19
  • @KasperSouren, I think it just demonstrates a bug in bash function parsing as mentioned here... so this is no valid bash syntax. – 0x80 Sep 25 '14 at 13:30
11

If you need a method to check several servers at once that are on the same subnet, you can use Masscan to send a request to all of them: https://github.com/robertdavidgraham/masscan

An example configuration file can be found at http://blog.erratasec.com/2014/09/bash-shellshock-scan-of-internet.html:

target = 0.0.0.0/0 //CHANGE THIS TO THE PROPER SUBNET
port = 80
banners = true
http-user-agent = shellshock-scan (http://blog.erratasec.com/2014/09/bash-shellshock-scan-of-internet.html)
http-header[Cookie] = () { :; }; ping -c 3 209.126.230.74
http-header[Host] = () { :; }; ping -c 3 209.126.230.74
http-header[Referer] = () { :; }; ping -c 3 209.126.230.74
//change the above 3 Ip addresses to the IP of the machine you send it from.

The machines that are vulnerable will send you a ping back. According to the followup blogpost by the author, there might be some configuration required.

  • How can I check just one server? – CharlesB Sep 26 '14 at 10:30
  • @CharlesB just remotely connect to the server and execute one of the oneliners on this page. or enter the full IP of the server with subnetmask /32. – Nzall Sep 26 '14 at 10:45
  • Thanks; couldn't edit it, but it must be target-ip instead of target. If I test my router, the ping command isn't detectable... Is there another command to prove that exploit – CharlesB Sep 26 '14 at 10:57
  • SSH into the router and do what Eliah Khan recommends in his answer. You need to do this directly through the router terminal. – Nzall Sep 26 '14 at 11:06
  • I have no SSH access to it, it's a closed box from our ISP. So no way to check it? – CharlesB Sep 26 '14 at 11:40
0

You can check your server submitting a CGI URL to the following online test:

http://shellshock.iecra.org

0

I wrote a quick test which either prints "vulnerable" or "not vulnerable":

env x='() { :;}; echo vulnerable; exit;' bash -c 'echo not vulnerable' 2>/dev/null

It also returns with an exit code of 2 if your version of bash is vulnerable, if you want to use it as part of a script.

  • Tested with versions 3.2.51(1)-release (x86_64-apple-darwin13) and 3.2.53(1)-release (x86_64-apple-darwin13). – colevk Sep 27 '14 at 0:12
0

You can try ShellShocker, which is a CLI utility which can check a CGI script as so:

python shellshocker.py http://example.com/cgi-bin/possibly-vulnerable-cgi.cgi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.