Re: If you do not sanitize CGI input @DainB
I was initially sceptical, but looking into the problem, it appears that Apache and other web facing services actually do accept some information and then passes into CGI-bin scripts as environment variables. Variables such as REMOTE_IDENT and REMOTE_USER are examples documented in rfc 3875.
This is where the problem lies. If Apache, or whatever, does not do any checking (and why should it, it would have to second-guess what is meant to be passed into CGI-bin programs), and allows the variable to be set up in the way described, and then for any reason spawns a bash, the extra code will get executed as part of the bash setup before any script starts running.
It is not that the function gets set up and can be called, it's that the extra code appended to the function definition gets executed at the time bash starts.
Look again at the proof of the bug at the shell level. I set the following environment variable up. Note this is just a variable, not a function at this time, and I can actually be running any shell (csh would need a setenv command to set it up).
never_run='() { : ; } ; echo "Vulnerable"'
This sets up an environment variable in the same pattern as bash uses to allow exported functions to work. When a bash starts, it effectively evals all of the environment variables in the new shell which will either set a variable up in the new shell, or will in this case define a function 'never_run' which would execute a null shell command and then exit. What the function does is completely irrelevant. What is important is that while the new shell evals the string to set the function up, it then also runs the code after the second semicolon. It does this immediately, not when the function is called. So in the example above, if I export the new variable
export never_run
and then start a bash, any bash, it will execute the code. So,
$ bash -c date
Vulnerable
Fri Sep 26 11:03:57 BST 2014
runs it, as does just entering a new interactive shell with bash by itself. Note that I've never run the function it's set up. This is where the danger lies. I'm sure that when bash was written, it seemed like a elegant way of exporting functions to subshells. It is clever, but obviously not thought through.
Apache is a limited examples, as it should run as a non-root user, and if set up properly, will run in a chrooted environment (not that this will prevent all information leakage). But the same exploit may be available in any poorly written service that passes user-specified data on to another command through the environment variables.