Why is the ability to define functions in an environmental variable not a security risk in itself?
It is a security risk. That's generally why you can't do it when switching to another context (remote control of a system, changing users, etc).
If you have the ability to create any environment variable you want, there are any number of potential ways you can execute arbitrary code.
Take $LD_PRELOAD
as an example. If you have the ability to set that variable, you can replace library functions, and stick your code in there. You can set the $DISPLAY
variable, and redirect the X display the program connects to so that you get control of the app.
This is why things like sudo
strip the environment of all variables. sudo
only allows a few select variables through. And of those variables, it sanitizes them (it passes through the $TERM
variable, but it won't if it contains unusual characters).
I'd say it is, when bash is your /bin/sh. It's a not feature of bourne shell, and I'd bet it's not a feature of posix shell either, in fact they might want to expressly forbid it.
Bash is really more of korn derivative shell, than a bourne shell, despite its name, and its the only Korn like shell that has the feature, and in my opinion it's kitchensink feature that has no practical virtues. Developers who avoid bash features for standards, like the bourne shell, the posix shell, or the ksh88 subset that modern shells have in common, or in other words, committed themselves to good practices, and standard idioms, are shocked when their software is on linux and mac and now potentially vulnerable, since the exploit authors are free to use the 'bashisms', despite their intents. As far improved compatibility, when invoked as /bin/sh, over other korn shell derivatives, it's only if /bin/sh is your login shell, or interactive shell, when bash behaves more like a bourne shell, than a korn shell, but when used in scripts you're free to do anything that bash can do, and it never complains or warns you that you are using features that really korn shell features, or unique to bash.
I'll try to persuade you that it's kitchen-sink feature, with 2 cases: you're an embedded dev, who makes devices like routers, network-attached-storage 1st bigger env, means more , memory, so, more cost, so less profits, so, if this was a reason to consider to using this feature of bash, shouldn't you instead use FPATH and autoload, ksh88 features instead? instead of passing the whole function byte for byte in the environment? You could even consider parsing and the pruning the environment wholesale, before it it gets to a shellscript that could misparse a variable, like just filter out ^$(.*)$ , and the like...
That does underscore what's unique about this, it doesn't matter what the variable is, and the script doesn't have to reference or use the variable, it could still be vulnerable.
#!/bin/sh
exec /usr/local/myapp/support/someperlscript.pl
For everthing else under the sun, the above is should as safe as the perl script, you're not using the any variables how could you misparse any? Changing to
#!/bin/bash -norc
exec /usr/local/myapp/support/someperlscript.pl
Doesn't help either, this had nothing to with ENV or anything like it -- everybody gets burned because bash needs to be unique. The fact that bash version 2 has the issue, to me proves that nobody ever uses this feature for their applications, because otherwise it should not have lurked around this long. And what's worse there's basically no avoiding this feature . Here's an example with: with 'su -', which if you would ask someone, the explanation would be it discards the environment, check the man page, and you'll find just 99.9% . I tested that right way, since on this system /bin/sh is root's login shell, and /bin/sh is bash BUT, in this example I try to harden my .bash_profile. I renamed my existing for root (which is enabled), but my thinking was if su, then possibly sudo, anyway, I changed to this:
exec env -i TERM=vt102 LOGNAME=root USER=root HOME=/var/root /bin/ksh -i
So, I'm actually tossing the environment completely, and use a minimal env, and then running a shell that shouldn't have the issue, in place of current process. Then in place of the standard example try:
%dock='() { echo -e "\e[2t\c"; echo dockshock;} ; dock' su
This illustrates how it has nothing to do with parsing any particular function, and an exploit can refer to and use, the function. You can imagine the function having logic to test if root, etc. In this case, it's just a modified form a function to iconify or dock a terminal window, using an escape sequence, that's pretty standard, so after I clicking to deiconify, I see dockshock -- but, so what? Now try this:
%TERM='() { echo -e "\e[2t\c"; echo dockshock;} ; TERM' su -
And, guess what? The window gets sucked into the dock. Here's what it looks like afterwards..
%TERM='() { echo -e "\e[2t\c"; echo dockshock;} ; TERM' su -
Password:
dockshock
# env
_=/usr/bin/env
HOME=/var/root
LOGNAME=root
TERM=vt102
USER=root
# echo $0
/bin/ksh
#
So, so, much for that! The exported functions actually have priority over rc scripts. You can't dodge it.