4

You know this sudo stuff:

Defaults env_reset

which makes environment injection impossible. I was wandering if this functionality can be obtained from bash script directly, 'from inside'?

At least part of it can, that is for sure. Example:

#!/usr/bin/env php
<?php
//...

// sanitizes $PATH
putenv("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"); 

// unsets $LD_LIBRARY_PATH, as it should be in Ubuntu
putenv('LD_LIBRARY_PATH');
//...

Can we do env_reset in running script like sudo does and how?

EDIT:

I'm not looking for the way to do it 'from outside' like env -i command but from inside of script itself. My intention is to ensure security no matter who (what user) and how(under which circumstances, i.e. env variables) runs it.

2 Answers2

4

bash itself uses some environment variables. By the time bash is started and ready to interpret its first command, it's already too late, a malicious environment can have had bash do damage already.

You need the environment to have been sanitized before bash is called. You can wipe the environment with the clearenv() C function on most systems or you could just call execve() on your script and pass an empty list in the envp parameter.

Even with a script that contains:

#! /bin/bash -
:

(: being a special builtin), if the environment contains SHELLOPTS=xtrace PS4='$(reboot)', the reboot command will be invoked upon :.

If bash is dynamically linked, LD_PRELOAD/LD_LIBRARY_PATH can make bash run arbitrary code as soon as it's invoked.

bash also honours the locale's charset for its parsing, so with LOCPATH and LC_* variables, you can have even the #! /bin/bash - line invoke arbitrary code (by making #!/bina characters blanks for instance).

See also:

env SHELLOPTS=noexec any-bash-script

That stops bash from doing anything.

Those are just a few examples.

Also note that the environment variables are not the only things that a command inherits on startup and that may affect its behaviour (like arguments, umask, limits, current working directory, open file descriptors, signal disposition, controlling terminal...).

1

You can find your exports with export -p or simply export, and replace the declare -x with declare +x on each line to unexport it:

eval "$(export|sed s/-/+/)"

If you put this at the beginning of your script, then no environment variables will be passed through to the programs it executes unless you explicitly export them yourself. You'll probably want to export locale and TZ variables, and TERM, and more...

Toby Speight
  • 8,678