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:
- It must start with the exact string
() {
, with exactly one space between )
and {
.
- 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:
- bash accepts function definitions in arbitrary environment variables, and
- 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:
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.
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.