Re: Taint and Shellshock
by shmem (Chancellor) on Sep 27, 2014 at 08:08 UTC
|
{
local %ENV = (
PATH => '/bin:/usr/bin:/usr/local/bin",
IFS => " \t\n",
LOGNAME => $ENV{LOGNAME}, # propagate values known to be secur
+e
...
}
...
system( ... )
}
update: corrected IFS} to IFS, addded propagation of secure ENV variables
perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
| [reply] [d/l] |
|
|
Perhaps my choice of language was unclear - by 'wipe the whole %ENV hash' I meant localize the hash and set explicit values prior to shelling out. Perl is vulnerable to Shellshock because an environmental variable makes a side run and it's not in the set that Perl considers dangerous for an external call. In the perlsec docs, the only recommendations are regarding 5 specific variables which are the 5 that taint considers dangerous (please correct me if I'm mistaken). It seems like this issue might warrant increasing the scope of taint to consider any tainted value in %ENV dangerous to the shell (thus breaking billions of scripts worldwide....)
#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.
| [reply] [d/l] |
Re: Taint and Shellshock
by LanX (Saint) on Sep 27, 2014 at 09:46 UTC
|
Sometimes elements of the parent environment need to be passed through
Shouldn't this line avoid all potential Shellshock exploits?
s/^\(\) {.*// for values %ENV
Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
BTW: Couldn't fully test cause my Perl doesn't seem to be exploitable! (?)
| [reply] [d/l] [select] |
|
|
While in theory this seems sound, it still feels like the classic black-listing that always seems to fall prey to some clever escaping scheme. Perhaps I'm being paranoid, but it seems like best practice should have any spawned processes firewalled off from anything you didn't explicitly give it.
#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.
| [reply] |
|
|
While in theory you can whitelist keys which need to be passed thru from parents env to bash, you'll hardly be able to avoid dangerous values without some heuristics...
Like forbidding anything which looks like an env-function.
That's what my regex does in a generic way, ie erasing magic values starting with () { .
You are free to combine it with further defense measures.°
But I doubt you can efficiently realize an individual validation for each string format (like PATH, HOST, IP, USERNAME, ...)
Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
°) something like (untested)
local %ENV = map { $_ => kill_func $ENV{$_} } @whitelist
| [reply] [d/l] [select] |
|
|
|
|
Re: Taint and Shellshock
by Don Coyote (Hermit) on Sep 27, 2014 at 10:18 UTC
|
I have an example of a piecemeal solution. This is the sort of thing that you are suggesting to prevent doing by setting up a localised environment?
Using File::Find I was having some warnings regarding insecure dependencies so I took to the debugger
I solved untainting of directory paths by localising the environment variables such as PATH,CDPATH,IFS and using the hash argument form of the find subroutine.
file( { wanted => \&wanted, untaint => 1 }, '.' );
However I continued to get insecure PATH dependancy warnings through debugger and its use of Term::Cap Using the perl debugger (-d switch) Term::Cap shells out and gives me warnings. I fixed this by assigning a literal path right before the eval.
Having localised the environment in my script, will I need to also localise for the debugger too? How do I do that?
code excerpt Term::Cap version 1.16 lines 239 - 275 Term::Cap meta-source lines 251-254 being of particular interest. my workaround being commented '# op fix'
DoC
enlightenment is the true goal
shellshock is a penalty shoot out | [reply] [d/l] [select] |
Re: Taint and Shellshock
by Anonymous Monk on Sep 27, 2014 at 02:12 UTC
|
I take it above is just a basic example (or else you would lose values of QUERY_STRING, REMOTE_USER, etc.)?.
| [reply] |
|
|
Right; presumably, you'd properly scope your localization if you had interest in other environmental variables, and propagate any values of interest. For my own development, I rarely shell out to do something other than invoke a command line utility for heavy numerics, with validation performed at the script level. If you trust externally set environmental variables to pass information to your CLI, I don't understand why you'd bother with taint in the first place.
#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.
| [reply] |
Re: Taint and Shellshock
by parv (Parson) on Sep 27, 2014 at 10:51 UTC
|
Regardless of the shell problem, is taint mode not the default in wide use due to the need to clean up things (certainly is the case for me)? If that is one of the argument, then what about the time spent on writing tests? Or, is the later more valuable than the former?
| [reply] |
|
|
…is taint mode not the default in wide use…
Not in my experience. :( And when arguing against the practice, and discovering 100s of scripts have to be fixed (some in rather deep ways) with it on, the wide spread manager will say: “We can’t afford to do anything about that right now.”
| [reply] |
|
|
Taint has wide usage, but it only limits passing certain environmental variables through. If the CGI request sets BAD_VAR = rm -rf /, Perl will happily pass that through to your executable without untainting because it doesn't expect your child process will use it (in my understanding).
#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.
| [reply] [d/l] |
|
|
Perhaps I don't understand the parent node as it was intended, but if I do correctly grok it, I think it's misleading, at best.
Oversimplifying a bit, when the -T CLI option is on, anything that comes from outside the script is "tainted."
Untainting data (be it ENV, $vars or anything else) can be fairly easy... but often is anything but 'easy' or simple. Consider, for example, data received as input from a form on a website.
However, take a simple case, where login_data (an ID and yeah, this is old) was supposed to be five digits -- no more, no less, and nothing that's not an (arabic) digit. Since the user entry is tainted, the cgi in use untaints the login_data (to the site owner's satisfaction) by checking that the id received consists of exactly five digits:
unless ( $value =~ /^\d{5}$/ ) # UNTAINT
{
out_badlog();
warn ("bad after UNTAINT\n");
exit;
}
Ascertaining that the five digits comprise a valid ID is a different topic and is performed in another part of the script.
So, moving on to this from perlsec:
"SECURITY MECHANISMS AND CONCERNS
Taint mode
Perl automatically enables a set of special security checks, called
*taint mode*, when it detects its program running with differing real
and effective user or group IDs. The setuid bit in Unix permissions is
mode 04000, the setgid bit mode 02000; either or both may be set. You
can also enable taint mode explicitly by using the -T command line flag.
This flag is *strongly* suggested for server programs and any program
run on behalf of someone else, such as a CGI script."
perlsec offers much more of relevance to the immediately previous comment from kennethk.
There's more in perlfaq7.pod about determining "if a variable (emphasis supplied) is tainted" ...after which pf7 offers these gems:
" You can use the tainted() function of the Scalar::Util module,
....See also 'Laundering and Detecting Tainted Data' in perlsec."
Frankly, I (for just one, I hope) was unaware (because of far too cursory reading of its docs) that S:C offered capabilities there. I hope this belated epiphany is useful to others.
Updated: Para 1 added and paras 2,3 and 4 edited for clarity
| [reply] [d/l] [select] |
|
|
|
|
|