XSS,CGI && Template Toolkit
David Dick
david_dick at iprimus.com.au
Mon Nov 18 12:56:59 CST 2002
Ended up just using a custom stash. Sample code is attached, i needed
to override the _assign method as well because there was an inheritance
problem but this seems to vary with your version of TT, so you may not
need it. You can also use this to inherit from Template::Stash::XS if
you want to. (Just change the ISA stuff). As has been noted on the TT
mailing list, the Stash isn't the best place to do this sort of stuff,
because _ideally_ what you want is to apply this sort of filter _after_
all the other filters in the template, but it works and it was quick to
code ;).
Uru
Daniel Walmsley wrote:
>Doesn't TT2 have a built-in html filter? [% myval | html %]
>
>-----Original Message-----
>From: David Dick [mailto:david_dick at iprimus.com.au]
>Sent: Wednesday, 6 November 2002 6:19 PM
>To: melbourne-pm at pm.org
>Subject: XSS,CGI && Template Toolkit
>
>
>Got a bit of a problem with Cross Site Scripting. The way I've been
>writing web apps is by using $cgi->param to suck in values from the user
>and using the Template Toolkit to generate the html. However, CGI.pm
>seems to assume that you'll use the CGI.pm routines to output html, so
>the param method unencodes everything it can, while the CGI.pm output
>commands encodes them. Translated..... <INPUT TYPE="TEXT"
>NAME="Something" VALUE="<SCRIPT>"> will be translated by
>$cgi->param into <SCRIPT> and the print commands will reencode it as
><SCRIPT> to protect against Cross Site Scripting attacks. The way
>i've been thinking, CGI.pm does do the correct thing, the place to
>encode all of that stuff is in the output routine. I can't find a easy
>way of doing this in Template Toolkit. I think I need a automatic
>FILTER or something. Anyone else have this problem or come up with an
>easy solution?
>
>
>
-------------- next part --------------
package MyStash;
use strict;
use Template::Stash();
use HTML::Entities();
use vars qw(@ISA);
@ISA = qw(Template::Stash);
sub get {
my ($self, $ident, $args) = @_;
my ($result) = $self->SUPER::get($ident, $args);
$result = HTML::Entities::encode($result);
return ($result);
}
sub _assign {
my ($self, $root, $item, $args, $value, $default) = @_;
my $rootref = ref $root;
my $result;
$args ||= [ ];
$default ||= 0;
# print(STDERR "_assign(root=$root, item=$item, args=[@$args], \n",
# "value=$value, default=$default)\n")
# if $DEBUG;
# return undef without an error if either side of the dot is unviable
# or if an attempt is made to update a private member, starting _ or .
return undef ## RETURN
unless $root and defined $item and $item !~ /^[\._]/;
if ($rootref eq 'HASH' || UNIVERSAL::isa($root, __PACKAGE__)) {
# if ($item eq 'IMPORT' && UNIVERSAL::isa($value, 'HASH')) {
# # import hash entries into root hash
# @$root{ keys %$value } = values %$value;
# return ''; ## RETURN
# }
# if the root is a hash we set the named key
return ($root->{ $item } = $value) ## RETURN
unless $default && $root->{ $item };
}
elsif ($rootref eq 'ARRAY' && $item =~ /^-?\d+$/) {
# or set a list item by index number
return ($root->[$item] = $value) ## RETURN
unless $default && $root->{ $item };
}
elsif (UNIVERSAL::isa($root, 'UNIVERSAL')) {
# try to call the item as a method of an object
return $root->$item(@$args, $value) ## RETURN
unless $default && $root->$item();
# 2 issues:
# - method call should be wrapped in eval { }
# - fallback on hash methods if object method not found
#
# eval { $result = $root->$item(@$args, $value); };
#
# if ($@) {
# die $@ if ref($@) || ($@ !~ /Can't locate object method/);
#
# # failed to call object method, so try some fallbacks
# if (UNIVERSAL::isa($root, 'HASH') && exists $root->{ $item }) {
# $result = ($root->{ $item } = $value)
# unless $default && $root->{ $item };
# }
# }
# return $result; ## RETURN
}
else {
die "don't know how to assign to [$root].[$item]\n"; ## DIE
}
return undef;
}
1;
More information about the Melbourne-pm
mailing list