develooper Front page | perl.perl5.porters | Postings from April 2008

Re: Taint (PL_tainting, SvTAINTED_on, SvTAINTED_off, SvTAINT)

Thread Previous | Thread Next
From:
Paul Fenwick
Date:
April 15, 2008 06:56
Subject:
Re: Taint (PL_tainting, SvTAINTED_on, SvTAINTED_off, SvTAINT)
Message ID:
4804B3B6.9070103@perltraining.com.au
G'day Nicholas / p5p,

Nicholas Clark wrote:

> Well, it seems to be something Larry wanted:
> 
> http://public.activestate.com/cgi-bin/perlbrowse/b;p=524,2687/mg.c@1528#L
> 
> and (as best I can work out that code) it gets turned on automatically
> whenever you're not root, and either your user IDs don't match, or your group
> IDs don't match.

That makes sense during start-up.  If our EUID and RUID don't match then 
we're running setuid (or with some other oddness), and we should be very 
careful.  It makes sense to act with caution when our data is being provided 
by one set of privileges, but we're running with another.

> in addition to that. I'd infer that it's intended to add taint mode for people
> who aren't aware of it, rather than to be any recommended way to enable taint.

Again, sensible during start-up.  But not sensible afterwards.  For example:

#!/usr/bin/perl -wl
use Scalar::Util qw(tainted);
print "Taint is ${^TAINT}";
$< = 1001;
print "Taint is now ${^TAINT}";
print "My path is $ENV{PATH}";
print "Path taint is ",tainted($ENV{PATH});
__END__

When run as root, this cheerfully informs me that my path is completely 
clean.  Tweak it for @ARGV, and everything in there is clean too.

I can't see WHY you'd want to enable taint mode, but have all the things 
you'd never want to trust considered clean that was set before that point. 
What makes it worse is because they're all clean, an arbitrary part of the 
program can't tell if a piece of data has been properly sanitised; the 
information is simply not there.

> I'm not convinced on the "false sense of security" part.

I am!  I use taint mode (along with 'use re qw(taint)' to protect against 
accidental untainting) for:

	* Protection against mishaps where environment variables are
	  set when they shouldn't.

	* Protection against mishaps where data from my database
	  may end up near something executing as code (ie, the shell).

	* Protection against data entering my database before being
	  properly validated and normalised.

	* Segmentation between unvalidated and validated data.

	* A whole swag of protections when it comes to the filesystem.

	* Protection against accidental mishaps with <> in an
	  untrusted environment.

	* Many of the above happening in modules that my code
	  is using, even if I haven't written those modules.

You're right that taint is no substitute for thinking.  However taint isn't 
meant as a substitute, it's meant as a safety belt; potentially catching the 
things that one didn't expect.  I regularly replace Perl's built-in open 
with one that checks all arguments for taintedness before opening[1].  That 
certainly SHOULD make it more difficult for me to accidentally open the 
wrong file and disclose data I may regret.

Imagine the following subroutine:

	use Scalar::Util qw(tainted);

	sub do_something_dangerous {
	    my @clean_args;

	    ${^TAINT} or croak "I only run in taint mode";

	    # If we have tainted args, sanitise them ourselves.
	    # sanitised() croaks if anything looks fishy.
	    if (map { tainted($_) } @_) {
	        @clean_args = sanitised(@_);

	    # Otherwise, our args are already safe.
	    } else {
	        @clean_args = @_;
	    }

	    launch_tactical_strike_against(@_);
	}

Here it's fine for us to pass in tainted data, it'll get laundered 
automatically.  But if taint mode had started 'part-way' through the 
program's execution, the data we've passed in may not be sanitised, but it 
may not be tainted, either.  That's very, very bad.

I personally find it chilling to think that taint mode could be turned on 
part-way through a program, where I've potentially already loaded code that 
I didn't want (via PERL5LIB), and all the data I'd like to check (eg, user 
or network input) has already been marked as clean.  I would much rather 
perl leave the taint switch off when changing unix privileges, so ${^TAINT} 
can reliably indicate if we started in taint mode.

Perl requires that a program with -T on the shebang line must also be 
started with -T on the command line for this very reason.  I certainly hope 
we're not planning to change that behaviour!

I still maintain that changing perl's tainting behaviour after it's already 
started is a bug, and breaks the fundamental design principles of taint.

Cheerio,

	Paul

[1] The standard behaviour is to skip taint checks if a file is open for 
reading.  You can even get creative and duplicate an existing filehandle 
using tainted data if you open something like "<&=0".

-- 
Paul Fenwick <pjf@perltraining.com.au> | http://perltraining.com.au/
Director of Training                   | Ph:  +61 3 9354 6001
Perl Training Australia                | Fax: +61 3 9354 2681

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About