6 ms·
> This feature is documented under the -f option of the export built-in command. The implementation detail of using an environment variable whose value starts
by ahy1 12y ago
> This feature is documented under the -f option of the export built-in command. The implementation detail of using an environment variable whose value starts with "() {" and which may contain further commands after the function definition is not documented, but could still be considered a feature.
This undocumented implementation detail is also a limitation on the use of regular environment variables, and should be documented. When reading documentation about a mechanism, I expect that special magical strings which change behaviour of the mechanism are clearly documented. If such documentation had existed, someone might have noticed it and guarded against it.
> Assumedly programs like apache filter out environment variables properly. But unfortunately, in the validation of input data, they fails to validate correctly input data because they don't expect that data starting with "() {" will be interpreted by their bash child processes. If there's a bug, it's not in bash, but in apache and the other internet facing programs that call bash without properly validating and controlling the data they pass to bash.
It isn't easy to validate and control data against an unknown magical feature in one of many possible shells.
> But on the other hand, it is free software and not difficult to check the source to see as the nose in the middle of the face, what is done. When reusing a component with missing specifications and lacking documentation, checking the source of the implementation should be standard procedure, but it has clearly not been done by Apache or DHCP developers.
I think the shell is specified in POSIX/SUS. Checking the source of all possible open-source shells would be a huge job. I don't know how they should check source code of the closed-source shells. I don't blame them for using the environment variables according to available documentation.
Edit: typo
- fabulist 12y agoI 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 toxic environment variables is infinite -- are we to scan the entire PATH for each environment variable to make sure it isn't dangerous? What if the CGI script updates PATH? There is no way to solve this problem with sanity checks. I've yet to peek at the source, but I'm told this feature is vital to implementing things like backtick operators. I think it is too dangerous however, and I don't want shellshock to become a class of bug rather than an instance of toxic environment variables. We're going to have to rip this feature out and re-implement large portions of functionality. The author is right that this is a product of bash being written in a more trusting time. This is not the first nor the last time the 1970s security models will come back to bite us. edit: forgot reference: [1] http://seclists.org/oss-sec/2014/q3/741 http://seclists.org/oss-sec/2014/q3/741 edited to add: Also, Apache does have a mechanism to filter out toxic environment variables; headers are added as HTTP_HEADER_NAME, because its generally the names of environment variables that allows them to be dangerous and not their content. Executing code as a result of parsing the value of an environment variable with no special meaning is a vulnerability.
- vertex-four 12y ago> 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. If you can set arbitrary environment variables, you're pwned and have always been pwned. You can set all manner of interesting things, including LD_PRELOAD, to control the execution environment and potentially execute arbitrary code. EDIT: Putting random data in an environment variable where you pick the name should always be secure, though, which is an assumption that most of *nix makes.
- FooBarWidget 12y agoBut the problem with Shellshock isn't random environment variables. It's random environment variable VALUES in well-defined environment variable names. It's pretty well-known that there are certain dangerous environment variables (like PATH, LD_PRELOAD) that should not be blindly set. But CGI only sets CGI environment variables like PATH_INFO, as well as HTTP_. That even these can be dangerous because bash executes code on any* environment variable, is completely unexpected.
- pbhjpbhj 12y agoIs this really a loose typing issue: we give Bash data that should be of type "display text" (a sub-type of string I suppose) and it treats that data as type "executable command" (also a sub-type of string). Would it be possible to wrap|tag input to bash so that only when a program|script sets the env variable with string that's typed as "executable" does bash even think of exec-ing it. I guess that removes some of the hack-ability and would need major rewriting of bash. I'm a layman trying to do CS ... what could possibly go wrong!
- vertex-four 12y agoThe issue is that the environment isn't a bash-specific thing. Anything can and regularly does set environment variables, and there's no space in there to set a flag for "this is executable" - if it's in the value, anything can set that flag, and the problem here is triggered by programs setting environment variables from external data.
- scintill76 12y agoYeah, I hope I never have occasion to walk through an undocumented minefield, I mean collection of "features", designed by this person. I say this without animosity to bash devs. I think some blame can be shared. But putting it all on people you expect to understand under-documented behavior and "implementation details" in every possible version of every possible flavor of /bin/sh is madness.
- kcbanner 12y agoI believe this just applies to bash, not sh?
- scintill76 12y agoOn some systems, they are one and the same. /bin/sh is often symlinked to /bin/bash, which is making this so exploitable. /bin/sh is invoked by system(), popen(), etc., and referenced in script "shebangs" (#!/bin/sh at top), so I meant that nobody necessarily knows what "flavor" of /bin/sh they're going to get.
- nailer 12y agoThere are other methods of IPC other than shell variables. The shell is a known insecure environment, which is where there are limits on setuid for shell scripts. By letting everyone on the Internet set shall variables Apache and whatever DHCPd (ISC?) did something they could have known would have bad consequences whether this feature/bug existed or not. The only data Apache needs to control is Apaches.
- icebraining 12y agoFrom 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).
- ygra 12y agoLots 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.
- asveikau 12y ago> 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...
- danielparks 12y agoI 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().
- philh 12y agoHow is it different to set some environment variables and then call out to a shell script, versus to set some environment variables and then call out to a perl script, or a binary compiled from C?
- TeMPOraL 12y agoIt'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 data. There is this extra step of saying "this is data, not code" that strips the external input from executability. (for the same reasons, if your templating engine is just concatenating strings and not building the page out of trees, you're doing it wrong, but it's a topic for another day) It's a problem you get when you believe in "the Unix way" a bit too much. Yes, everything is text, but no, not everything has the same semantics.
- philh 12y ago> 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 cgi script, whether it's C or perl or shell, it makes the user input available as data in defined locations. There's a bug in bash which causes some of that data to be executed, but there's no way to protect against that class of bug. This isn't a case of "you should have protected against sql injection attacks". It's a case of: there is a bug in your sql server, such that the query "select from Users where username='rm -rf /'" will execute "rm -rf /"*.