bash stores exported function definitions as environment variables. Exported functions look like this:
$ foo() { bar; }
$ export -f foo
$ env | grep -A1 foo
foo=() { bar
}
That is, the environment variable foo
has the literal contents:
() { bar
}
When a new instance of bash launches, it looks for these specially crafted environment variables, and interprets them as function definitions. You can even write one yourself, and see that it still works:
$ export bar='() { echo "bar" ; }'
$ bash -c 'bar'
bar
Unfortunately, the parsing of function definitions from strings (the environment variables) can have wider effects than intended. In unpatched versions, it also interprets arbitrary commands that occur after the termination of the function definition. This is due to insufficient constraints in the determination of acceptable function-like strings in the environment.
This is considered insecure because variables are not typically allowed or expected, by themselves, to directly cause the invocation of arbitrary code contained in them. Perhaps your program sets environment variables from untrusted user input. It would be highly unexpected that those environment variables could be manipulated in such a way that the user could run arbitrary commands without your explicit intent to do so using that environment variable for such a reason declared in the code.
vulnerable
appears in the output. The main problem is that bash is parsing and executing the code after the function definition as well. See the/bin/id
part of seclists.org/oss-sec/2014/q3/650 for another example. – Mikel 3 hours ago