
Not a bash bug - informatimago
http://paste.lisp.org/display/143864
======
ahy1
> 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
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 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
> 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
But 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
Is 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
The 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.

------
saurik
The original author of bash (a friend of mine, which is why I have this
context) has been being interviewed by various newspapers today regarding
shellshock, and finds the idea that he might have anticipated the number of
ways people integrated bash into various systems (such as with Apache allowing
remote control over environment variables when running software in security
domains designed to protect against unknown malicious users) quite humorous.
Apparently, it has been an uphill battle to explain that this was all coded so
long ago that even by the time he had already passed the project on to a new
developer (after having maintained it for quite a while himself) the World
Wide Web still wasn't a thing, and only maybe gopher (maybe) had been
deployed: that this was even before the Morris worm happened...

> In an interview Thursday, Mr. Fox, the Bash inventor, joked that his first
> reaction to the Shellshock discovery was, “Aha, my plan worked.”

[http://mobile.nytimes.com/2014/09/26/technology/security-
exp...](http://mobile.nytimes.com/2014/09/26/technology/security-experts-
expect-shellshock-software-bug-to-be-significant.html)

~~~
_yosefk
"Quite humorous"?

* In Unix, shell scripts and shell subprocesses are everywhere, and are supposed to be everywhere.

* Environment variables are passed across subprocesses by default, you need to explicitly filter the environment to prevent that.

Therefore, if you write a shell, the reasonable assumption is that it's going
to be integrated into pretty much all "systems"/programs running on a Unix box
with this shell, and environment variables will travel from everywhere to
everywhere.

Of course the feature isn't a "bash security bug"; it's just one of those
endless poorly documented, weird special cases which together make up what we
know as "Unix".

And the answer to anyone shooting themselves in the foot, whether it's one
person or a billion, is "you should have read the documentation" \- and now,
apparently, "you should have read the source".

It's a good thing this kind of "design philosophy" is absent outside the field
of computer programming. Generally the vendor should be the extremely diligent
party, and the user is assumed to be reasonably naive - even if the user is a
professional (think power tools, etc.) It is only programmers, for some
reason, who think that it's perfectly fine to add whatever features they want
to their code without much worrying about consequences, and leaving the
worrying to the users.

~~~
sp332
Since the sub-process runs as the same user as the original process, it wasn't
really considered a security problem. The problem is calling a sub-shell
without sanitizing the environment first. It's really a bad idea to connect
unsanitized user input to a turing-complete system of any kind.

~~~
_yosefk
Ahem. Every web server passes "unsanitized user input" to "Turing complete
systems". You have a right to expect certain things from subsystems regardless
of their "Turning completeness".

* A file system should store your bytes, though nothing prevents a file system written in C from executing, say, logged HTTP requests as commands.

* A CGI script should sanitize form data, though nothing prevents a PHP script from blithely shoving unsanitized data into SQL queries.

* And a shell should pass environment variables to subprocesses, though nothing prevents it from interpreting variable values (or names, or a combination of names, values and the time of day) as commands.

As I said - I don't think it's a security bug in bash, just another one of
endless misfeatures. It's about as crazy to interpret environment variable
values as code because they have a special-cased form as it would be to
interpret, say, file names as code, or certain byte sequences passed to the
write() system call as code, etc.

~~~
quesera
The point is that, when bash was written, there were few mechanisms for
executing code as another user. There were servers/daemons, but they did not
execute user code.

Of course some people would pipe to shell in their .forward file and
eventually get pwnt, but it was a freshman mistake, and the damage was
isolated.

Once you reach the point of executing a shell with an euid other than your
own, it's not the shell's job to sanity check your actions.

The web has changed the execution model thoroughly. And people now do lazy
things based on their loose understanding of flexible execution models.

This is neither a bug in bash, nor a bug in Apache, etc. It's an integration
bug between two complex systems that were designed with zero-to-poor knowledge
of each other.

~~~
derekp7
I'm not quite so sure about that. One of the early examples I've seen of Unix
use (I think Ken Thompson was actually in the video, from early 80's) showed
using the various tools to process file data that got downloaded from
somewhere else (where that data was supposedly created by another user). So if
you had a script that did:

    
    
        cat downloaded_file.txt |\
        while read inputline
        do
            #some processing
            #call another shell program
        done
    

In this case, bash would still be vulnerable even without the Internet
involved -- just processing a data file you got from Bob in Accounting.

~~~
saurik
Only if you not only set a variable to the contents of data from that file,
but then also exported that variable to the environment: don't do that (why
would you anyway? ;P).

------
myhf
> 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's absurd to think that a transport layer should be responsible for
"validating" all possible contexts in which the data it transports could be
used. How is apache supposed to know the difference between _using_ a magic
string and simply _mentioning_ it? How is apache supposed to know what magic
strings apply to all possible subprocesses of sh that inherit environment
variables? A program that receives user data has to be responsible for
validating that data, and it's not productive to characterize the lack of
validation as a "feature" just because it can be used to provide
functionality.

This kind of misguided thinking leads to practices like mod_security refusing
to allow comments that contain the magic strings "1=1" because they might be
trying to inject SQL into something.

~~~
claudius
The point here is that Bash was not designed to receive untrusted user data in
environment variables. On the other hand, Apache/dhclient was designed to
receive untrusted data, but then handed that over to someone which did not
expect untrusted data without validation.

In other words, if Apache/dhclient wants to put things into environment
variables, it absolutely should make sure to do this properly and indeed to
take into account all possible contexts.

~~~
scintill76
So if I write a new shell called rash, that executes anything in an env var
between, say, backticks, and install it as /bin/sh, it's Apache's job to
neutralize backticks in untrusted data? I can agree with some of the things
you say, but this seems to be the logical conclusion, and it's crazy.

The most consistent moral I'm deriving here, is that shells are for executing
arbitrary commands in a flexible environment, so don't even touch them if
that's not what you want. This applies to Apache, CGI wrappers, any other kind
of web development.

~~~
danielweber
_install it as /bin/sh,_

At first glance, I think that's your problem.

Fundamentally, though, you can't always point to "it's this one component that
is broken." There is the classic example that was used to criticize
Authenticode, which was Microsoft's way of dealing with mobile code back in
the 1990's. It said "all the code is signed, so if something breaks, you know
who to sue."

Well, imagine two programs:

1\. One of them formats your hard drive, and on installation puts itself into
your Quick Start list.

2\. One of them runs every single program in your Quick Start list at start
up.

Which piece of code is responsible for formatting your hard drive?

~~~
scintill76
It does indeed seem wrong to put magical behavior into /bin/sh, but that's
exactly what's going on in this bug. bash is often installed as /bin/sh and is
doing extra, non-standard, sparsely-documented behavior. I don't know that it
really violates POSIX et al, but it definitely goes on the list of factors at
fault.

And yes, I agree it's difficult to assign blame.

------
guelo
> The problem is that 5 years later, new software was developed (apache, dhcp,
> etc), that uses bash in child processes

I don't think this history is correct.

At the time, most systems used sh as the default non-interactive shell. The
other shells such as csh, ksh and bash were considered to add interactive
niceties, but programmers and sysadmins expected scripts to use sh.

One of the reasons sh doesn't have a lot of wiz-bang features is that it needs
to stay compatible and portable across all the different Unixes so that all
the scripts, past and present, will work. And sysadmins liked this
conservative approach.

It wasn't until the rise of Linux, and the aliasing of /bin/sh to point to
bash, that sysadmins started becoming comfortable with running bash as the
default non-interactive shell. And that was only because bash promised to be
fully compatible with sh. And bash was compatible but it also added new
scripting features. But most developers and sysadmins rejected using these new
features because you would lose portability to sh systems if you did so. That
is until now, with the dominance of Linux and portability becoming less of a
concern.

So really this bug is the fault of bash's embrace-and-extend strategy.

------
meelooo
It's an "internet tech" bug. Every developper should know how hard it is to
parse textual data vs well defined binary in a secure and fool proof way. Yet
every damn internet piece of infrastructure is based on handling textual data,
mash it up, pass it around, escape and unescape it in hundreds of stupid
formats. No wonder that most security troubles surfacing over the years are
some form of abuse of this crazy design flaw: buffer overruns, sql injection,
the openssl bug a few month back and now this. Let's go back to sanity and use
well defined binary protocols where there is no damn way to send a command by
text but only very explicit semantics, and stop the unix way of thinking that
text should be more than a human interface. Text should never be used as a
command language in between complex programs. Period.

~~~
icebraining
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.

~~~
meelooo
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, most of the time you will never
validate the data and you have no way to ensure that you are not actually
handling a bomb. If the protocol was binary there is no way in hell you would
be tempted to pass it's data without validation to an external program because
you'd have to respect the API and because there would be not way to just send
a bunch of commands. The same goes for sql injections, url buffer overflows,
etc. Free form text should only be used for actual human textual data and
should NEVER be the interface in between programs. It's way too fuzzily
defined to serve as a protocol.

~~~
icebraining
_If the protocol was binary there is no way in hell you would be tempted to
pass it 's data without validation to an external program because you'd have
to respect the API and because there would be not way to just send a bunch of
commands_

I assume you're talking about Apache - but Apache had no way of validating the
data. The protocol just said "this is a blob from the client", which any
binary protocol for the task must be able to handle. Apache had no business
validating it, anymore than it should validate any other content - how should
it know what makes it valid?

Bash, on the other hand, just received that blob and treated it as an
executable. It wouldn't matter if the protocol between the server and bash was
binary, since it was a valid value as far as the protocol was concerned.

The problem here is the hidden channel between Apache and bash, which never
actually talk directly to each other (it's through the CGI binary) but still
pass data. It has nothing to do with text protocols.

~~~
meelooo
no, the problem is that you can treat any kind of text data as an executable.
You can try to fix this by adding mountains of complexities and excuses but
would still be true: as soon as you have text enter the equation you need to
escape/encode/decode and parse. Every time you do that you add more complexity
than is needed, and also you add many ways to abuse the programs and create
"interesting bugs".

------
jerf
This seems like contrarion nonsense. Therte is no sane reason for a variable
definition to result in code execution. There is no sane reason for a function
definition to result in (immediate) code execution. Part of those things very
purpose is not to result in execution, because we have explicit syntax for
asking for execution, precisely because the purpose of these constructs is not
to execute. If anyone ever intended this, then they intended what is still
best described as a bug... It is not as if intention is proof against being a
bug! I have written bugs with full intent.

Disclaimer: I may be crabby from a busy week of mitigation. Still, I don't
hold any particular ill will for the original bug. But a bug it is.

~~~
mturmon
It is an amazingly powerful bug. In what system can you plug a magic value
("() {") into a variable which everyone expects to hold static data, and have
the value of the variable interpreted as code and executed spontaneously on
invocation?

And: The magic value is undocumented.

And: Any instance in the entire tree of calls will do this.

Some of this is strictly on bash. But some of it also has to do with the
environment feature of Unix, which is basically a god object with all the
power and temptation ("look what we could get for free if we let it be a
function!") that entails.

------
masklinn
> 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.

Bullshit, this may well be perfectly valid data and web servers are not in the
business of shielding shells against their own misfeatures.

And if they were where would they stop? It would require that webservers do
arbitrary context-sensitive data analysis of everything doing through in case
this is a malformed JSON string triggering a bug in GSON while that is data
injected unescaped into an SQL variable and the other one's too big for an
underlying C buffer.

You can only end up with a webserver refusing to do anything, because some
idiotic application somewhere may misuse or misunderstand _anything_ it lets
through.

~~~
avar
Your comparison doesn't make any sense. It's an obvious requirement for a JSON
parser that it be able to parse input from arbitrary sources, including
malicious ones. It's not so obvious that a shell should have to deal with
malicious environment variables, due to the reasons outlined in the original
post.

~~~
iopq
It's the requirement for the JSON parser, not for apache. It's like saying
apache should quote SQL strings automatically so that SQL injections can't
happen. This is not apache's job!

~~~
sp332
It's the job of the CGI program, which is the same code that would have
responsibility for sanitizing environment variables before calling bash.

~~~
masklinn
There's nothing for the CGI caller to sanitise, how could and why should it
know how arbitrary programs are going to arbitrarily misinterpret what it
forwards? The CGI script could be Python eval()'ing it or Ruby interpreting it
as a local file to display or delete, and it's no business of the CGI caller
that they do.

All the CGI caller can and should do is forward correct data as defined by RFC
3875, the rest is _not its job_.

> sanitizing environment variables before calling bash.

The CGI caller may not even be calling bash, then what? Should it remove
anything which looks like valid PHP code because it's calling a PHP CGI? Oh
but now the PHP CGI uses system() which creates a subshell which is still
holed, and we end back with: if it becomes the CGI caller's job to cleanup
data which could be misinterpreted by application code, the only thing it can
do is stop working entirely.

Now if you want a _mod_bash_is_retarded_ prefilter feel free to implement one,
but it most definitely is not mod_cgi's job to fix that crap, mod_cgi's job is
to correctly implement RFC 3875, and the number of times bash is mentioned in
RFC 3875 is _0_.

~~~
vidarh
I think you're in violent agreement with the comment you responded to in this
case (especially judging with what he's written elsewhere on this thread).

He's saying if Apache passes a request to mod_cgi, which spawns "someapp", it
is not Apache, but "someapp" that should sanitize the environment before _it_
calls bash.

(and of course if the developer/admin has chosen to write their script to be
run by bash, that's their mistake)

------
0x0
Still sounds like a bug in bash to me.

What if I have a printer called "() { :;}; echo lol", so I manually export
PRINTER="() { :;}; echo lol" (see [http://www.tldp.org/HOWTO/Printing-Usage-
HOWTO-4.html](http://www.tldp.org/HOWTO/Printing-Usage-HOWTO-4.html))

I don't think this was the intended behavior even 25 years ago. :)

~~~
xioxox
The saner way to implement this bash feature would be to have a single
environment variable containing inherited shell functions. A special prefix is
an alternative, but a bit harder to filter.

------
timtadh
I personally feel bad for Chet about this whole thing. For those of you
(probably most of you) who do not know Chet has been maintaining Bash for free
in his spare time for the last 25 years. He began working on it because he was
not satisified with the shells available at that time:

    
    
        In 1989 or so, I was doing network services and server support for
        [Case Western Reserve] University (CWRU), and was not satisfied with
        the shells I had available for that work. [1]
    

I had the priviledge of hearing Chet speak about his experiences maintaining
Bash.[2] From my perspective he has done a really great job over the years
making software that many people love to use and abuse.

So while this is a really bad network security situation for the internet at
large I think it is dubious to hold Chet or even Bash at particular fault.
Rather, we are all at fault. We have been writing software that just shells
out to Bash or sh or z-shell for years because it is convient. We could have
easily have written our subprocess code in better ways but it was easy to use
shells and we used them, even when we didn't really understand them.

[1]
[http://www.computerworld.com.au/article/222764/a-z_programmi...](http://www.computerworld.com.au/article/222764/a-z_programming_languages_bash_bourne-
again_shell/)

[2] The venue was Link State a student run conference here at CWRU

------
kazinator
This is completely wrong in numerous ways.

Firstly, the "security concern" is definitely a bug.

It is related to bugs in a feature; nobody is saying that that feature itself
is a bug, though many are saying it's a "misfeature". So the idea that the
feature itself is a bug isn't something that requires opposition.

The idea that it's the Apache people's fault somehow, because they didn't
inspect the implementation of something that they rely on, is wrong.

> _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._

Firstly, the CGI mechanism doesn't rely on Bash; it relies on the passage of
environment variables.

Secondly, for the shell language, there is a specification: POSIX. Someone
calling a shell implementation should be able to rely on the interface
contract. Nowhere in POSIX is it documented that code from environment
variables is to be executed by the shell.

Apache can run on systems that don't have Bash. A shell other than bash can be
used for running a CGI shell script. You don't get the source code,
necessarily; how can the Apache developers inspect the source code of a
proprietary shell on a proprietary Unix?

Even if the Apache or DHCP developers were to (insanely) take responsibility
for this flaw, the workarounds in their code would be Bash-specific hacks:
basically they would have to parse anything that goes into an environment
variable and validate that it doesn't have the syntax which exploits the Bash
issue. That would clearly indicate that it's a Bash problem.

What also indicates that it's a Bash problem is the way it is being handled:
fixes have been issued against Bash, not against other programs. The fire is
where the smoke is, generally, and that's where you pour the water.

Lastly, _please don 't post diatribes to a code paste hosting service; it is
not your soap box_. Thanks!

------
mcguire
This was my initial opinion of the bug, as well. The parent processes are in
control of the environment and should be validating input.

On the other hand, after thinking about it, there are a number of reasons why
I decided that this is at best a misfeature of Bash.

It is incredibly undocumented. I've been a Unix guy for over 25 years, and
I've been using Bash for most of that time. (Sorry, David Korn.) I've used
Bash _a lot_. But I've never heard of this thing.

It violates some ill-defined, personal, un-thought-about assumptions about
environment variables. An environment variable with executable code? That's as
terrifying as LD_LIBRARY_PATH, and _that_ is very well known. One reason I've
probably missed this feature is that it is something I would never consider
using.

In my opinion, it's almost impossible to secure this on the parent process'
side. Sure, the parent can look for magic Bash strings, but.... This isn't
just Apache, it's potentially every other network accessible program that
calls a shell, and _that_ is a very common thing to do in Unix.

Finally, consider some of the special behavior of execlp and execvp:

"If the header of a file isn't recognized (the attempted execve(2) failed with
the error ENOEXEC), these functions will execute the shell (/bin/sh) with the
path of the file as its first argument. (If this attempt fails, no further
searching is done.)"

You could end up starting a shell without knowing.

------
wahsd
"Security in internet software and protocols were often just not considered at
all in that time..." I find that a rather perplexing issue with many,
especially software based products and research. How do you, in early, usually
time, effort, support, and resource constrained stages of a project or
research discover and identify all dependencies and requirements to the best
of your knowledge so that there is not a type of runaway train effect where
momentum is gained and speed is accumulated but it is frequently overlooked
that there are all kinds of things like security, anonymity, etc. that are not
being considered even though they will invariably become monumentally
important.

Take the internet today in general as a huge example of that issue; it was
never developed with anonymity or privacy or security in mind and here ware
are, horrified of even just the tip of the iceberg that was revealed through
Manning and Snowden. If the early researchers and engineers had built the
early technologies with fundamental, most basic human considerations in mind
we might not be looking down the barrel of a dystopian dawn.

So my question is whether anyone is aware of a method, procedures, techniques,
etc. to plan for such a paradox?

~~~
informatimago
If you look at early RFCs, you will see that if they mention security
considerations at all, it's often just to mention that they haven't been
addressed at all.

Specifically, the literal string "Security issues are not discussed in this
memo.' is found 568 times in the 3000 first RFCs. (6 times in the RFCs from
3000 to 5887).

When searchers were inventing the internet, they just put aside security
considerations. In a way, security was enforced at the boundary, by
universities controlling their teachers and students who could use it.

When the internet becomes a public network, where anybody can send packets on
it, of course security considerations become a priority, but the protocols
weren't designed for security. Like IPv6, we'd need to design a new set of
protocols for this public internet, taking into account security
considerations as a priority.

But given the speed with which IPv6 is adopted, you can guess with what
readiness a new set of secure protocols will be adopted (you'd also have to be
able to trust them, that no NSA or other backdoor is hardwired in those new
protocols).

In short, this is not a simple situation and there is no simple solution.

------
userbinator
_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._

If this is considered an "implementation detail", then I'm even more convinced
that the whole idea of hiding implementation details, and thus these
surprising (mis-)features, is fundamentally flawed.

 _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._

There is absolutely nowhere in the official bash manual that mentions the
special behaviour of environment variables with values starting with '() {',
not even in the "differences from POSIX/Bourne Shell" list, so the natural
expectation is that _any_ sequence of bytes not containing the 0 byte (since
this is a C interface) can be put into the contents of an environment
variable. On the other hand it does have an extensive list of reserved
variable names which have special meaning.

To quote the POSIX spec on environment variables (emphasis mine) -
[http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_...](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html)
:

 _The values that the environment variables may be assigned are NOT RESTRICTED
except that they are considered to end with a null byte and the total space
used to store the environment and the arguments to the process is limited to
{ARG_MAX} bytes._

Thus the reasonable expectation is that Bash behaves according to the POSIX
spec; it's even mentioned in
[http://www.gnu.org/software/bash/manual/bash.html#Major-
Diff...](http://www.gnu.org/software/bash/manual/bash.html#Major-Differences-
From-The-Bourne-Shell) that "Bash is POSIX-conformant."

The fact that the function used to evaluate imported function definitions was
named parse_ _and_execute_ (), and is basically the same function that
executes regular commands at the prompt, was what stood out to me the most
upon hearing of this behaviour although in retrospect, it wasn't all that
surprising.

This is a bug that, by any other name, would be just as disturbing.

------
aidenn0
It took a lot of discussions with pjb on irc for me to decide he is not
actually a troll. His is very literal. The part where assigning a particular
variable to _any_ environment variable causes arbitrary code execution is a
bug.

The part where you can define functions by setting environment variables is a
feature. It would be far better if the variable names needed a prefix (e.g.
BASH_FN_foo='() {...}')., but even without that change, fixing this bug still
preserves the case that allowing arbitrary data into the values of a whitelist
of environment variables is safe.

In general, allowing modifications to a subset of the environment (and by this
I mean the entire system environment, not environment variables) needs to be
safe. Allowing programs to upload arbitrary data to /tmp/uploads is safe,
allowing programs to upload to e.g. ~/.profile is clearly not safe.

In PJBs world it is not possible to set any environment variable to any value
without reading the source code of every program that might possibly be called
by any of your children. This is clearly not tenable.

~~~
skybrian
If an environmental variable is like a file, this bug is like automatically
executing code stored anywhere in the filesystem if the file happens to
certain a magic number. Using a prefix (if documented) is like looking in a
certain directory. It should have been obvious that scanning ALL environment
variables is a bad idea, if not for security than for correctness, because
interpreting data belonging to another program is likely to cause
unpredictable behavior.

~~~
aidenn0
agreed

------
julie1
So an ENV is a dict string => string with this feature we have a dict that
point to functions. Basically it is an object. It could even has been used for
passing structured data with their own functional compiler. Or objects with
stateless (lambda) functions/methods usable for parallel computing.

Oh fuck, this feature is a wonderfull feature in a controled environment for
passing objects/code over a simple octet stream. With safe computer paradigm.

We could have done RPC easily with xinetd + and shell scripts. With PAM we
could have even be able to use kerberos to control the security...

I could have done lots of things... I still can ...

Bash I still hate you for not documenting this, and more YOU Advanced Bash
Scripting guide for being so awesome and missing that. ABS you failed me.
[http://www.tldp.org/LDP/abs/html/functions.html](http://www.tldp.org/LDP/abs/html/functions.html)

------
whoisthemachine
I agree with this. Whenever something is interacting directly with a shell (or
any other program that can execute passed in code dynamically for that
matter), it should sanitize the input as to be certain nothing gets executed
later, unless it wants something to be executed later.

Whether that be Apache (if it's passing data or commands directly to shell
that contain data from the external environment) or a CGI script it is
calling, whatever happens to be interacting directly with the shell should be
sanitizing its inputs.

~~~
AgentME
And what sanitization should Apache be doing to all of the environment
variables? A blacklist against "() {"? That syntax is specific to bash, bash's
support for it is undocumented, and it can be in any environment variable.
It's more than a bit arrogant of bash to have an undocumented claim on all
environment variables.

------
drvdevd
I think you cannot really say who has the bug in this case, from this point of
view. The problem is that in order to blame one component (e.g. Apache) over
another like bash, you would have to have a "rigorous" spec of the entire
stack -- from network drivers to user facing programs, in order to say either
"this is doing something unspecified" or is flat out wrong. This may be
possible, but it also goes somewhat against the UNIX philosophy with which all
of this was built in the first place.

------
lutusp
> I would argue that the bash security concern is not a bug. It is clearly a
> feature. Admittedly, a misguided and misimplemented feature, but still a
> feature .... The problem is that it was designed 25 years ago. Apache didn't
> exist yet for five years!

The linked article's premise requires that the bug/feature be present when
Bash was first written, not be the result of more recent changes, a a time
when the risks were obvious. I can't show this, but I doubt it.

~~~
informatimago
Yes, this part of the code is basically unchanged in all versions from the
oldest I could get (1.14.7).

What made me look for it, was a suspicion that it was some backdoor added more
recently. But apparently no, it's a feature that always existed in bash
(granted, an ill-advised and ill-implemented undocumented feature, but still).

------
putzdown
False premise: "Unintentional failure is not a failure." Lack of intention for
a failure certainly weakens the _ethical_ culpability of the action, but it
doesn't weaken the technical or pragmatic severity of the failure. What's the
point in saying the bash failure isn't a bug. It's an unwanted behavior. What
else _is_ a bug?

------
dllthomas
My understanding was that using this "feature" would sometimes lead to a crash
of the executable. That seems to me to be clearly just a bug.

Even absent that, contrary to the article, I think I'd still call this a bug
in bash - but the crash (presuming I'm recalling correctly) makes this
position absurd instead of just (IMO) incorrect.

------
erikpukinskis
I don't understand this situation at all. Are people using bash as a secure
jail and expecting it not to be able to arbitrarily execute code and access
the user's complete environment?

I think the maintainer is right. Bash was never marketed as a secure sandbox
and anyone who uses it as such is taking that risk on themselves.

------
codeskyblue
Even through bash is open sourced, But the author of dhcp or apache can't
spare many time to see bash source code. It's not a bash problem and not dhcp
problem. Just because every code got a some bug hiddened.

------
mariusz79
I agree with the OP. Bash is a scripting language. If you use it, you must be
aware that you can damage the system. If you allow your script to get input
from the untrusted sources it's your job to sanitize it.

~~~
clarry
> If you allow your script to get input from the untrusted sources

This wasn't the problem. The problem wasn't with scripts getting untrusted
input. The problem was with _bash_ getting untrusted input -- input that isn't
supposed to be evalled in the first place.

------
1wd
Undocumented feature = bug.

------
sandstrom
Using Nginx, how could one filter/drop/reject http requests where a http
header start with "() {"?

I know patching `bash` is most important (and I have). But it would give some
extra comfort.

------
xiaq
> The problem is that it was designed 25 years ago.

It's just my imagination, but I keep picturing someone who did point out the
possible security risks but was then dismissed as being too paranoid.

------
felipelalli
"I would argue that the bash security concern is not a bug. It is clearly a
feature. (...)" The default excuse of all programmers. :)

------
panzi
I don't agree. bash is meant to be a sh replacement, compatible with sh. So
any correct use of sh has to give the exact same result under bash. bash
should only extend sh in a way where the bash script would be an error under
sh.

bash might not be intended to be that way, but it is assumed by developers to
be that way, which means it has to be that way (or it can never be used as
system shell).

------
mc_hammer
ofc its not a bug its a security vulnerability. Where hes wrong is having an
undocumented unnamed unknown function that has eval abilities is plain
idiotic; who cares if its a bug?

------
INTPenis
All the programs at risk here should really be using rbash.

------
senko
The bug may be bash's, but it's the entire chain that makes it a serious one:
[http://senko.net/shellshock](http://senko.net/shellshock)

------
giancarlostoro
So basically "this code has no bugs, just undocumented features".

