Subject: | CGI::SSI mishandles #if expr directives |
It appears that CGI::SSI attempts to solve #if expr="..." directives by
wrapping them in a Perl eval string. This can cause security issues (as
well as lots of warnings) when the directive is something like:
<!--#if expr="$HTTP_USER_AGENT=/Mozilla\/[1-4].[0-9]+/ &&
$HTTP_USER_AGENT != /MSIE [5-9].[0-9]+/" -->
since the user can then set their user agent to something that will be
evaled and thus have more privileges than they should have.
The code responsible is:
# line 463
sub _test {
my($self,$test) = @_;
my $retval = eval($test);
return undef if $@;
return defined $retval ? $retval : 0;
}
# line 513
sub if {
my($self,$expr,$test) = @_;
$expr = $test if @_ == 3;
$self->_entering_if();
if($self->_test($expr)) {
$self->_true();
} else {
$self->_suspend();
}
return '';
}
Note that evaling this isn't the correct thing to do for any test of
equality as it will instead test for ability to assign. So a more
simple expression:
<!--#if expr="${var}=1" -->
will always return true if ${var} is changeable even if it was
originally not 1. I expect that it will fail for regular expressions
for the same reason.
I realise that the correct behaviour (de-constructing what kind of test
it is) will be a lot harder to implement, but it would be great to be
able to handle apparently simple SSI such as:
<!--#if expr="(${HTTP_USER_AGENT} = /Mozilla\/4/) &&
(${HTTP_USER_AGENT} != /MSIE/)" -->
Netscape styles
<!--#elif expr="(${HTTP_USER_AGENT} = /Mozilla\/4/) &&
(${HTTP_USER_AGENT} = /MSIE/)" -->
<!--#if expr="${DOCUMENT_URI}=/flashy-site/" -->
Flasy MSIE stlyes
<!--#elif expr="${DOCUMENT_URI}=/plain-site/" -->
Plain MSIE styles
<!--#endif -->
<!--#else -->
You must be using Opera or sumfin?
<!--#endif -->
My understanding of SSI #if expr structures come from
http://www.ssi-developer.net/ssi/conditional-expressions.shtml and a few
other on-line tutorials.
Thanks!