- 论坛徽章:
- 0
|
前几天跟Apile谈起了cgi的安全问题,并谈到了tainted模式。回去后偶查了一些关于tainted的资料,并看到一个如何判断某个变量是否tainted的函数如下:
sub is_tainted{
my $var=shift;
my $blank=substr($var,0,0);
return not eval {eval "1 || $blank" || 1};
}
这个函数让偶郁闷了半天,于是在mailing list上发贴求教。perlmonk的Jeff很热心的回答了偶的问题,引用如下:
If a variable is tainted, then any substring of that variable is also
tainted. In addition, it is illegal to eval() any string that is tainted.
The inclusion of a tainted string inside another string makes that whole
string tainted.
Therefore: if $var is tainted, the $blank will also be tainted (even
though it's a substring of zero characters). If $blank is then tainted,
then the code
eval { eval "1 || $blank" || 1 }
will return false (since the eval { ... } catches fatal errors, and the
eval "1 || $blank" raises a fatal error because $blank is tainted), and
therefore,
return not eval { eval "1 || $blank" || 1 };
returns true, stating that $var is indeed tainted. If $var wasn't
tainted, then
eval "1 || $blank" || 1
returns 1, and
return not eval { 1 }
returns false, stating that $var wasn't tainted.
*whew*
Frankly, I find the 'eval "1 || $blank" || 1' silly, since the whole
reason the '... || 1' is needed is since $blank is a blank string and the
code '1 || ' is invalid Perl. Long story short, I'd have written:
sub is_tainted {
return not eval { eval 1 . substr($_[0], 0, 0) };
}
It's much more concise. If $_[0] isn't tainted, then
not eval { eval 1 . substr($_[0], 0, 0) }
->
not eval { eval 1 }
->
not eval { 1 }
->
not 1
->
false
whereas if $_[1] is tainted, then the eval { ... } returns false since a
fatal error is raised because
eval 1 . substr($_[0], 0, 0)
is illegal if $_[0] is tainted.
偶仍有所不明,于是再问Jeff:
1)eval "1 || $blank";
When $blank is tainted,the $blank is false,but "1 || $blank" should return
true,because "true || false" will return true always.Isn't it?
2)why to call eval 2 times here?
Jeff回答:
If $var is tainted, then even though $blank is an empty string, it's
tainted also. That means the string "1 || $blank" (which is really just
"1 || " (which if it WERE eval'd would be a syntax error!)) is tainted by
association with $blank. And eval($some_tainted_string) is a fatal error.
If we didn't have the eval { ... } around the eval($tainted_string), the
Perl application would die with the "Insecure dependecy..." error message.
The outer eval { ... } catches this error.
So, when $blank is tainted, the eval "1 || $blank" doesn't even get as far
as executing the code inside it. It realizes it's ABOUT to eval() tainted
code, and dies; and that's what the outer eval { ... } is there for.
终于弄明朗了这个哈,大家也可看一下。 |
|