Can someone explain why apache cgi use bash? You can of course setup an environment without bash and execute your scripts. It's just an argument to exec*() after all.
It doesn't necessarily. But what it does do is pass information about the request in environment variables - that's step 1: attacker controls the contents of an environment variable. Then, if at any point the script invokes bash, or calls something like system(), exec() or popen() and has bash set as the default shell, then bash will run, with those environment variables set. That's step 2, and the server is now the attacker's.
And environment variables are typically inherited by subprocesses, so if the CGI script executes anything (that executes anything, recursively) that uses bash (including system() if /bin/sh is bash, e.x. on OS X) this bug becomes exploitable?
Ok, let me see if I have this straight, since I'm not seeing an end of the world situation here.
This requires a webserver to be running CGI (mod_cgi or whatever) and the get request has to go to a valid page, correct? So in this case `GET /cgi-bin/hello ... yada yada yada` /cgi-bin/hello has to be a valid location.
So, explain to me how this is any worse than any remote execution vulnerability in something like PHP?
> explain to me how this is any worse than any remote execution vulnerability in something like PHP?
Why does it need to be worse than something you might find in PHP? If it's a worm that's been found in the wild spreading by exploiting a remote execution vulnerability in bash and cgi, isn't that bad enough?
> Why does it need to be worse than something you might find in PHP?
Because that's what it's being hyped as, or more correctly hyped as "OH MY GOD IT'S THE END OF EVERYTHING" when in reality it appears that if you're not running ssh with forcecommands or a webserver with CGI enabled, you don't care, just like if you didn't run a webserver with PHP enabled a PHP vulnerability wouldn't really be much of an issue to you.
Think of it this way: this doesn't just affect webservers. It affects most unpatched bash instances. The vector of attack is through environment variables in bash. You could argue that 90% of the worlds' PHP servers will probably contain bash, but that the converse is not true: 100% of the worlds' bash instances may not contain PHP. Therefore, the attack surface is much larger and the attack vector much more basic to the way the OS works. Since environment variables are so "leaky" -- they are often spread between processes without any sort of checks -- there are essentially innumerable ways for an exploit to reach a vulnerable version of bash, both remotely and offline.
But it needs something to expose bash to the outside world. Without mod_cgi (or the like) or sshd with a specific configuration, a vulnerable bash isn't going to be remotely exploitable.
No, it doesn't. Bash is already indirectly exposed to the world by anything that calls system() with bash as /bin/sh. More library functions than you might expect are wrappers around external binaries (e.g. mail() calling /usr/bin/mail) on PHP, Ruby, etc. Their authors probably thought they were safe with escapeshellarg()-like functions, but now any user-controlled env var set for whatever reason, not just CGI, is an attack vector, and not just through HTTP and not just through headers.
It is correct that PHP's mail() function will fork a shell:
sendmail = popen(sendmail_cmd, "w");
Which calls /bin/sh to execute sendmail_cmd. However, two things must also be true:
1. /bin/sh is bash
2. PHP has set environment variables with user-provided data
#1 is often the case, but is much less common now than in the past.
#2 is not commonly the case, PHP does not even automatically create PHP variables from user-provided data anymore (because it is a terrible idea to put untrusted data into a trusted scope without sanitizing).
> It is correct that PHP's mail() function will fork a shell:
> sendmail = popen(sendmail_cmd, "w");
> Which calls /bin/sh to execute sendmail_cmd.
Are you sure? It looks like (at least by default) sendmail_cmd is a string constructed by putting sendmail_path (from php.ini) together with the various options passed to mail(). For most *NIX sendmail_path is going to be /usr/sbin/sendmail and so would execute /usr/sbin/sendmail -t -i to@someplace.com 'message string'
I haven't tried it, but that is the relevant line from the PHP C source. sendmail_cmd is a variable, so you're right, it will be expanded to whatever.
popen()'s man page says:
FILE *popen(const char *command, const char *type);
[..]
The command argument is a pointer to a null-terminated
string containing a shell command line. This command is
passed to /bin/sh using the -c flag
[..]
Which is where /bin/sh gets involved. PHP should be calling pipe/fork instead of popen IMO, I can't see the point in invoking a shell.
Which is where /bin/sh gets involved. PHP should be calling pipe/fork instead of popen IMO, I can't see the point in invoking a shell.
Ideally there would be something like a popenve() to simplify the process of opening the pipe(s) and passing arguments and environment.
There are also various other variations on the popen() concept, like my own popen3() implementations in C[0] (note that I'm not the only person to write a popen3; Python, Ruby, and probably other languages have their own).
However, I mimicked the real popen(), and my implementation uses /bin/sh as well. It would be easy to make a version of popen3() that accepts argument and environment arrays, but it would still be insecure if the environment was set to the calling process's environ pointer[1], and/or the command to be executed was a /bin/bash script.
From what I can tell you are affected only if you use CGI or the like somewhere in your response chain. AFAIK most people use http reverse proxies, phpfm, wsgi and the like. They are all unaffected.
It is not just CGI. It is any process that uses user-controlled environment variables anywhere, that later eventually happens to call something that calls something that calls system() or executes a shell script.
So CUPS printer servers at universities may be vulnerable. Dhclient may be vulnerable to malicious DHCP responses. Anything that calls out may be vulnerable (lots of mail libraries actually call /usr/bin/sendmail or the like; better hope they don't use system() or a bash /bin/sh to do it).
This is a big deal because there's a ton of stuff that uses environment variables that is and is not a web server, and very little time to track it all down before a black hat or oppressive regime gets there first.
What I don't understand is why everybody seems to think its necessary to start posting every script kiddies attempt at spreading their crappy ddos / botnet scripts via the vulnerability.
It's not worse, it's equal. But the thing is that people didn't think that this would happen and now they're affected. So yes, that's quite 'drop your sandwich while you're eating it and go update your servers'
I think the "super-hype" is warranted. You've missed out a large number of possible ways this could be exploited, so the above advice would leave a lot of people vulnerable. Furthermore, because it's such a common thing to pass environment variables and to invoke bash, people expect far more attack vectors to be discovered as this unfolds. In addition the current patches rely on huge swathes of bash code being bug-free, we've already seen one patch circumvented and with so many eyes suddenly on code that wasn't closely inspected from a security angle for over two decades, I would bet on seeing far more things being found over the next weeks or months.
Are you certain that no process on your system ever sets an environment variable to a user-controlled value? Get patching.
Hypothetical: some GPG library is just a wrapper around /usr/bin/gpg. Maybe that library uses an environment variable to set a password that doesn't show up in ps. Maybe that library used system() instead of execve(). That password is now an attack vector.
See also /usr/bin/mail called by mail() functions in scripting languages, /bin/hostname, /bin/uname, etc. If any user-controlled variable is set in the environment, those calls become potential attack vectors
And how many of those are remotely callable? It is a local exploit without something that makes bash directly callable remotely.
That's why mod_cgi or sshd (in one configuration) make this bad, they execute whatever command passed by design. To do that with most everything else, you would need a remote exploit in that program, making the bash exploit somewhat moot in that case. Or you're not sanitizing your inputs in which case you have another problem anyway.
I haven't experimented yet, but I wouldn't be surprise if something seemingly innocuous like nzbget is vulnerable. It shells out to various extra processing scripts, setting a bunch of variables from the downloaded nzb file.
How about all those torrent clients? Do they safely shell out when doing transcoding stuff? I don't know - do you?
How about the absurd rube goldberg contraption that is modern email processing?
How about all of those scripts that crawl various web pages? Do they shell out anything, or set environment variables? Not just the ones you wrote, but any of the ones that are potentially being used within your organization? (it just takes one owned box in the network to gain a foothold)
Or you're not sanitizing your inputs in which case you have another problem anyway.
Sanitization is an orthogonal issue; no amount of escapeshellarg() would save someone from this issue, especially if the call to Bash is several layers of library calls and program executions removed from the developer's code (see pyre's comment: https://news.ycombinator.com/item?id=8368861).
Anything that allows user-input to end up in an environment variable, that later makes any[0] call to Bash (even with the Bash command user-sanitized), will trigger this.
[0] With the caveat that it's possible to limit the inherited environment variables, but this is rarely done, and even things like $PATH could be potential vectors depending on the code.
Commands can be:
portscan (scans a host for open ports)
tcpflood (try to keep 1000 TCP connections open to a host for a specified period of time);
udpflood (send UDP packets to all ports on a host with an payload of a specified number of 'A' characters for a specified period of time);
httpflood( send HTTP requests to a host for specified period of time [with HTTP Keep-Alive header]);
shell (execute arbitrary commands on the host);
google (use google to find other hosts to infect [targets modules.php]);
version (returns bot version)
All commands send status back via IRC.
There are several brazilian portuguese strings and comments, although is not clear if the author is brazilian.
Interesting stuff.