10

If setuid scripts take arbitrary environment variables, apart from a few black-listed ones like LD_LIBRARY_PATH, from the caller, does this not mean that any setuid script running #!/bin/bash directly or indirectly is a vector for local escalation of privilege?

A good answer would be an explanation of why this is or is not the case.

For example, many (most?) unixalikes now do not honour setuid on shell scripts (though they did when this bug/backdoor was introduced). But binaries may call shell scripts indirectly, so unless they explicitly clear the environment first is this not still a problem?

Ben
  • 3,697
  • 1
  • 18
  • 24

2 Answers2

7

Yes!

Binaries with a setuid bit and calling (directly or indirectly) bash through execve, popen or system are tools which may be used to activate the Shell Shock bug.

If these commands aren't taking care of clearing *env prior to run bash (or a shell script) then these binaries may be used to run any command (for example bash) with the privilege of root.

popen and system don't let the programmer the possibility to clean *env.

Here is a first draft easy audit to estimate this risk:

find /  -perm +4000 \
    -exec /bin/zsh -c "ls -dluT {} ; nm -a {} | egrep '(popen|system|execve)' && strings {} | egrep '/bin/(sh|bash)'" \; 2>/dev/null

This isn't a proof of risk, since the *env might have been cleaned before the fork of the shell. The only way to be sure is to read the source code.

And here is the result on an actual version of an highly used Unix:

-rwsr-xr-x  1 root  wheel  910848 Sep 29 16:31:18 2014 /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/MacOS/ARDAgent
             U _popen
/bin/bash

(Here the last time used is not a proof of an attack but of my own previous "draft audit".)

dan
  • 3,033
  • 14
  • 34
2

When bash is invoked in setuid (or setgid) context, that is when the effective uid is different from the real uid, then bash drops the privileges (sets the effective uid back to the real uid).

Exception to that is when using the -p or -o privileged (the SHELLOPTS variable is ignored, so privileged in there as well) or when invoked as sh.

In that case though, functions are not imported from the environment (nor are things like BASH_ENV, BASH_OPTS, SHELLOPTS for the same obvious reasons).

If they were, you wouldn't need the shellshock vulnerability to exploit it. Just exporting an echo function (or anything called by the script including paths like /bin/mount) would do.

Some setuid commands may chose to set the ruid to the euid. If they do and don't sanitize the environment and call bash (or any other shell), then game's over, shellshock vulnerability or not.

The libc's dynamic linker takes care of removing some variables that affect the libc or linker (LD_PRELOAD, LOCPATH, LD_LIBRARY_PATH...), but it's up to the setuid application to clear the rest if they invoke other commands like a shell (or python, or any other command whose behaviour can be controlled with environment variables), the typical sane approach being to clear everything except a sanitized whitelist.

A typical example of such an application is sudo.

By default (with the env_reset option on), sudo clears the environment, sets a few (like PATH, HOME, SUDO_USER...) and whitelists a few after checking their content like TERM or DISPLAY. Part of that checking specially takes care of variables whose content starts with ().

If env_reset is off (disabled by the user/administrator), then sudo still blacklists a few variables that affect various shells or other common tools (like PS4, BASH_ENV...) and those whose content starts with ().

So shellshock cannot be exploited by doing:

DISPLAY='() {(:);}; ouch;}' sudo trusted-bash-script

Now, it's possible that there are setuid commands out there that set ruid and don't check for variables that start with () and invoke bash (possibly indirectly), but again no need for the shellshock bug to exploit those.

A possible exception to that is apache's suexec. As far as I know, suexec sanitizes the environment but only white-lists some variables based on their name, not their content. Without CVE-2014-6271, that wouldn't be a concern as those variables names like QUERYSTRING, HTTP_USER_AGENT are not likely to match the name of a command, so it wasn't deemed necessary to block variables whose content starts with "() {", but in practice that means it's exposed to CVE-2014-6271.

  • An example of a vulnerable command is `schroot`. `schroot` runs some setup scripts with root permissions (ruid==euid==0). The environment is mostly clean, but at least a user-settable session name is passed on an environment variable. This allows privilege escalation. There is another attack vector that requires sysadmin action, `user-modifiable-keys` allows additional custom variables (even `ld.preload`, which as an envvar gets turned into `LD_PRELOAD`), so sysadmins should use caution when copying schroot configurations from random tutorials. – ninjalj Oct 08 '14 at 15:43