Live data from Hacker News

Not a bash bug

paste.lisp.org

101–110 of 189 posts

Re: Not a bash bug

#101
post #42

Earlier quoted context omitted.

From what I understand, Apache doesn't send them to bash. It sends the to whatever binary is configured to handle the request (using CGI), which were then calling bash unbeknown to Apache (but implicitly passing the same environment variables).

Lots of functions to start another process start a shell instead and is a command line to be executed, e.g. system or popen. The convenience in that case is that you don't need your own handling of $PATH or wildcards or argument parsing. It's pretty standard on UNIXoid systems.

> The convenience in that case is that you don't need your own handling of $PATH

You don't with execvp or execlp either.

> or wildcards or argument parsing.

IMO this is of dubious value from, say, a C program. Why "parse" the args? Just generate a list...

Re: Not a bash bug

#102
post #63

Earlier quoted context omitted.

I agree with all your points. I think the real bug is that all this stuff calls out to a shell at all. Sure, it's convenient, but it's basically eval().

There are two things to differentiate, in my oppinion. In most cases, the shell is just used to find programs in the PATH when a C programmer uses system(). And for that case, which is probably 99% of the time when /bin/sh is being invoked, it would make perfect sense to implement this with something that exhibits less attack surface. Taking the "dhcp-exploit" as an example (set a DHCP option on your server to "(){..…

> when a C programmer uses system()

I said it in another thread but this is almost always a mistake. The execve family is much less ambiguous about what gets passed to the program. Using it avoids this type of bug by not putting the shell where it doesn't need to be.

Re: Not a bash bug

#103
post #83
post #3

Earlier quoted context omitted.

I agree. This is an interesting idea, so I upvoted the paste. But I don't think this author knows how deeply the bug runs, either; the most recent way to exploit it is to export an environment variable of, say, ls to a bash function. [1] Usually the amount of toxic environment variables are considered to be finite; PATH, LD_PRELOAD, etc., etc. If the name of any executable on the PATH is dangerous, than the number of…

Plenty of other shells support backticks without the "export -f" magic. They must, as backticks are mandated POSIX behavior; few support "export -f" at all. (And at least one that did, the old Bell Labs post-v7 "Research Unix" shell, used only environment variables with embedded characters which couldn't easily be created by normal means, to avoid the risk of "magic processing" on things like TERM and HTTP_FOO.)

used only environment variables with embedded characters which couldn't easily be created by normal means

    SOMEVAR="`cat some_binary_file`"

Re: Not a bash bug

#104
post #64

Earlier quoted context omitted.

If the protocol was binary, exporting variables to subprocesses and exporting functions to subprocesses would go in different places, and Apache would know to send the one but not the other

How, if the protocol in question - the environment variables - has no concept of functions? The matter is that Apache and the protocols (HTTP and environment vars) are just being used as a tunnel between the attacker and bash. They can't pass functions via another channel because they don't know what functions are . All they know is they're passing blobs of data - which any protocol would do, binary or not. Bash happ…

The problem is that Bash is using the same channel for two quite different things - values and functions. It's doing that because the channel is a string; if there were a proper protocol for passing environment to subprocesses, that protocol would make a distinction between the two.

Re: Not a bash bug

#105
post #63

Earlier quoted context omitted.

There are two things to differentiate, in my oppinion. In most cases, the shell is just used to find programs in the PATH when a C programmer uses system(). And for that case, which is probably 99% of the time when /bin/sh is being invoked, it would make perfect sense to implement this with something that exhibits less attack surface. Taking the "dhcp-exploit" as an example (set a DHCP option on your server to "(){..…

> when a C programmer uses system() I said it in another thread but this is almost always a mistake. The execve family is much less ambiguous about what gets passed to the program. Using it avoids this type of bug by not putting the shell where it doesn't need to be.

Did you read the next sentence?

> And for that case, which is probably 99% of the time when /bin/sh is being invoked, it would make perfect sense to implement this with something that exhibits less attack surface.

Re: Not a bash bug

#106
post #65
post #56

Earlier quoted context omitted.

Your response sounds like blaming the world's oldest webserver for being the world's oldest webserver. CGI sucks, but telling the 1990s to go home and not come back until it has a secure mechanism of IPC just isn't helpful: this seriously isn't an Apache (or other CGI httpd) problem. As someone else said, traditionally only the names of shell variables have mattered, not the content. Apache exports most of its envars…

Unix domain sockets existed in the 90s and would have done the job adequately without evaling anything in transit. Apache transmitting data created by random people to CGI processes using environment variables is most definitely Apaches fault. It was a dumb idea in the 90s and it's a dumb idea now.

You realize that this isn't just an Apache problem. It's a problem with any network-accessible program, directly or indirectly.

Re: Not a bash bug

#107

Earlier quoted context omitted.

> if Apache/dhclient wants to put things into environment variables... it absolutely should ... take into account all possible contexts Sorry if I'm picking on you too much, but I noticed this and thought of an even better counterexample. By this logic, it's Apache's job to prevent SQL injections. It should know that a single quote, in one possible context, can terminate an SQL string, popping the SQL parser into a s…

> Sorry if I'm picking on you too much Don’t worry. > By this logic, it's Apache's job to prevent SQL injections. Curiously, I’d call this an example for my position, not yours: It is not the job of the SQL server to prevent SQL injections, quite the contrary, it is the job of the calling application to ensure that the things it tells the SQL server to do are actually safe. Similarly, it is the job of Apache to ensur…

> It is not the job of the SQL server to prevent SQL injections

True. But perfectly valid SQL shouldn't cause the SQL server to be exploitable. And the application has no idea which SQL statements are exploitable.

> Similarly, it is the job of Apache to ensure that the things it tells its child processes to do are safe.

True. But the unsaid assumption is "safe from the point of Apache". Not "safe from the point of some unknown exploit".

So it's reasonable for an application to sanitize what it passes to the shell, by dealing with known and documented issues. e.g. Don't pass "$FOO" in a string to system() and expect it to be treated as the literal "$FOO" string.

It's unreasonable to expect that the application know everything about the attack surface of everything it uses. Maybe there's a bug in an SQL library which causes the application to crash when a SELECT statement contains the text "crashme". This text is valid SQL, and it is entirely unreasonable to expect that the application "sanitize" such text.

In the same way, environment variables are strings. It's a bit surprising to discover that bash will execute code contained in random environment variables.

Re: Not a bash bug

#108
post #80

Earlier quoted context omitted.

It's not. It's the "calling out" part that is wrong. You should never call out to anything by passing untrusted user input directly. Any information that came from the outside must be explicitly passed as data through proper serialization mechanisms. For instance, you don't piece your SQL queries by concatenating strings. You use an abstraction layers, in which you code the query structure and you pass user input as…

> You should never call out to anything by passing untrusted user input directly. So if I call a CGI script with parameters foo=bar, what data should apache pass to the handler, if not something along the lines of the string "foo=bar"? When I pass the header "User-Agent: baz" and the handler asks for the user-agent, what should it be told if not "baz"? Environment variables are data, not code. When apache executes a…

The point of the OP is that if a program has chosen bash to be handler of untrusted user data, then the program has made the wrong choice, because bash is clearly (hindsight!, I'm not claiming I wouldn't have made the same choice) not designed or that purpose. A handler for untrusted user data should be a program specifically designed for that purpose, which should receive the data directly.

Similarly, if a Ruby or Perl script decides to call out to bash with untrusted user data, it's their mistake to trust bash with it, not bash's mistake that it wasn't designed for that use case.

It's perfectly possible to protect against this attack: don't call a generic program with untrusted user data.

Re: Not a bash bug

#109

Earlier quoted context omitted.

> when a C programmer uses system() I said it in another thread but this is almost always a mistake. The execve family is much less ambiguous about what gets passed to the program. Using it avoids this type of bug by not putting the shell where it doesn't need to be.

Did you read the next sentence? > And for that case, which is probably 99% of the time when /bin/sh is being invoked, it would make perfect sense to implement this with something that exhibits less attack surface.

I did. I did not find it explicit enough. There was no specific recommendation, for example. Moreover seeing the phrase "when a C programmer uses system()" is pretty jarring. There aren't enough warnings you can add to that to convey how much this gets misused and what a bad idea it usually is.

To me, use of system() is very indicative that you need to find another C programmer. There are few other answers to complete the phrase "when a C programmer uses system()".

Re: Not a bash bug

#110
post #31

Earlier quoted context omitted.

Please describe specifically how would that have helped. This has nothing to do with parsing text. The problem here is that Apache et all send untrusted data to a process that treats it as code. It wouldn't matter if HTTP was a binary protocol and if bash read a well defined bytecode instead. I mean, look at shellcodes.

You are describing the problem exactly: it all too tempting to pass text around from user input to command line arguments without any way to validate the text data and assume it's ok because it's easy. It's exactly the same arguments that goes in between static and dynamic typing in programming languages: static typing ensures some sort of semantics is respected. If you pass text around, because it's easy and fast, m…

I can craft malicious binary data just as easily to execute a function if you execute binaries that begin with a few magic bytes when you're reading input into a buffer.

You seem to be relying on some assumption that you have about human psychology for your security gain. Somehow people would never do that with a binary protocol, and text protocols make them more comfortable and trusting. At least they can read text protocols directly; binary protocols involve me trusting a bunch of middleware I'm using to read them, too, or writing my own (always great for security.)

Post reply on HN