Nathan Wiger <[EMAIL PROTECTED]> writes:
[...]
> =head1 Implementation
>
> This will avoid internals, but instead get into the details of how the
> implementation should *act*:
>
> 1. Have the tainting engine "trust" any variables declared
> when tainting is off. So:
>
> #! perl
> # engine assumes this is clean
> my $var = 'some_val';
> $^T = 1;
> $ENV{PATH} = $var; # safe
>
> So, the tainting engine could trust $var just as if it
> had been the string '/usr/bin:/usr/sbin'.
>
> 2. Nonetheless, have the tainting engine watch any tainted
> variables still. So, whatever scope (tainted or untainted)
> the variable is *initially declared in* is what it remains
> as:
>
> #! perl -T
> # this doesn't work, sorry
> my $unsafe_value = read_unsafe_value();
> $^T = 0;
> my $trick_var = $unsafe_value; # try to sneak...
> $^T = 1;
> $ENV{PATH} = $trick_var; # nope! insecure still!
>
> That way, the $^T variable would not allow someone to
> easily shoot themselves in the foot by accidentally
> untainting the wrong thing.
This is very different from the current model. perlsec talks about
"tainted *data*", not " tainted *variables*" (my emphasis). I believe
it does so for a reason -- it does not make sense to talk about
variables (if $x is tainted variable, how can "$x+2" be tainted
without being a variable?). In this way, we can talk about operations
which remove taintedness (substring extraction using m/.../), and the
others which preserve it. I doubt the same could be done for
variables. Some expressions don't even involve a variable! For
instance, your "read_unsafe_value()" has no variables, tainted or
untainted, in sight; why is it unsafe?
Unfortunately, this would mean your example above doesn't quite work.
One possibility is to say that $^T controls taint *checking*, but not
tainting itself[1]! That is, in the above code $trick_var's value is
tainted. Now you say "$^T=1; $ENV{PATH} = $trick_var;", which is
insecure (attempting to set $ENV{PATH} from an insecure value while
taint checking is on).
>
> 3. A true RFC: What to do about this?
>
> #! perl -T
> my $unsafe_value = read_unsafe_value();
> $^T = 0;
> my $trick_var = $unsafe_value; # try to sneak...
> $ENV{PATH} = $trick_var; # ???? ok ????
Here, $^T=0, so no taint-checking is done (sorry). Even "$ENV{PATH} =
$unsafe_value;" would work (sorry again)!
[...]
Another note: your examples with:
local ($^T) = 0;
$ENV{PATH} = read_config_file();
local ($^T) = 1;
is only using local() to confuse; it should be written with a block,
correctly restoring the old value of $^T.
Footnotes:
[1] For efficiency, you'd probably still want some command-line
option, perhaps -T itself, to say "this program involves taint
checking, so please keep track of tainted values". That way programs
that keep $^T == 0 (almost all of what I write) don't need to keep
track of tainting.
--
Ariel Scolnicov |"GCAAGAATTGAACTGTAG" | [EMAIL PROTECTED]
Compugen Ltd. |Tel: +972-2-6795059 (Jerusalem) \ We recycle all our Hz
72 Pinhas Rosen St. |Tel: +972-3-7658514 (Main office)`---------------------
Tel-Aviv 69512, ISRAEL |Fax: +972-3-7658555 http://3w.compugen.co.il/~ariels