Is there a short command to test if my server is secure against the shellshock bash bug?

  • 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.

    bash --version The bug effects versions of bash up to and including 4.3

    @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 `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 ... 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.

    I'd be a little miffed if my distribution is patching the code without bumping the version number *at all*.

    @chepner: why? There's a difference between the version reported by the program and the package version. Well, there can be, let's put it this way.

    Yes, but the package can indicate a divergence from the upstream using revision levels. If the package manager decides to ship a version of `bash` 4.3.25 along with their own patches, the package version should be something like 4.3.25-1.0, 4.3.25-1.1, etc, *not* 4.3.26, 4.3.27 or worse, 4.3.25, 4.3.25 with *no* change in version. Changing the package version is one thing; stepping on the upstream's (at least, a sane upstream's) versioning scheme is another. The whole *point* of a version number is to indicate changes in the underlying code.

  • Eliah Kagan

    Eliah Kagan Correct answer

    7 years ago

    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 :

    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 (, 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.

    Hmm, but if I can run bash then can't I already execute arbitrary commands on a system? How is this a vulnerability?

    If bash isn't the default shell, wouldn't it be easier to use the: bash -c "env x='() { :;}; echo vulnerable' bash -c echo this is a test" oneliner?

    @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 under "So far, HTTP requests to CGI scripts have been identified as the major attack vector."

    @Ajedi32 `/bin/sh -c` is a used heavily to start child-processes. If the environment can be controlled by an attacker then there's a problem - the most common case is a web server using the environment as a form of IPC when running a CGI scripts.

    @mr.spuratic Your example is `/bin/sh -c` which is not `bash` but just the basic vanilla shell process. So I am still not getting the true risk here. Granted this is all unintended usage. But if the user cannot get elevated privileges past what the parent process has, the risk is what exactly?

    @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.*

    @JakeGould It's true `sh` is only sometimes `bash`. This may be expected to mitigate the risk/harm somewhat. But even when not the system sh, bash is widely used for scripting, so arbitrary code execution is still possible. Commands after a function definition in an environment variable get executed when a bash script is run (as running a bash script, particularly from a shell or other process that isn't bash, involves running the bash executable to interpret it). Degree of risk for desktop users is unknown but malicious data (e.g., specially crafted files) processed via bash are still a risk.

    @somelooser28533 The caller needn't be bash for `env x='() { :;}; echo vulnerable' bash -c 'echo ...'`, just any Bourne-style (POSIX) shell or some other shell that accepts `VARIABLE=value` command syntax. With `env`, the shell could be just about anything, which may be why the test BadSkillz quotes uses it. `sh -c "env x='() { :;}; echo vulnerable' bash -c 'echo ...'"`, whether or not sh is bash, also works. Even in a non – Bourne-style shell, you don't need both `env` and `sh -c`.

    @EliahKagan I see the risk for servers under certain conditions, but if you look at Mac user forums—for example—there is this absolute panic that Mac OS X on a client level is at risk. And I honestly don’t see that. But appreciate your POV.

    @EliahKagan `“It's true sh is only sometimes bash.”` No, it is not a “sometimes” issue. `bash` is bash and `sh` is the standard Unix shell. If you do not understand that incredibly simple fact you really should not be advising anyone o security issues.

    @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.

    @EliahKagan I stand corrected. But `dash` is simply not `bash` and I honestly think the panic around “shellshock” will cause more problems than the exploit itself.

    I just patched my server and now I get the error after running the command above. Does this mean that I am still vulnerable to CVE-2014-7169 which claims the fix for 6271 shell shock is incomplete?

    @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 -So to get an idea of the degree of security that has been mitigated with the patch, what can an attacker do while exploiting the bug in 7169 that he could no longer do on a 6271 patched system?

    @user53029 Exactly. A tree is fixed. But is the forest in any true practical danger?

    Suggestion for a small improvement. If you prefix the test command with `env` it'll work from csh/tcsh as well.

    I use mac os x, and it shows up as vulnerable -- but there is nothing I can do about it for the time being, right?

    With the last patch (which avoids `eval`s on random environment variables) the original test should do fine, printing _nothing_ on a completely patched system.

    I do not get anything when I type this

License under CC-BY-SA with attribution

Content dated before 7/24/2021 11:53 AM