Bug 22223: Add filter to make item URLs safe in template output
This change adds a "safe_url" filter which takes a text input and
returns a Perl URL object which stringifies to a safe URL.
This change is only needed in the OPAC as the staff interface
handles the item URL display using Javascript not Template Toolkit.
0. Apply patch and koha-plack --restart kohadev
1. Create an item for a record using the following URL
https://koha-community.org?url=https%3A%2F%2Fkoha-community.org
2. Go to the OPAC for that record and verify that the URL is
not double-escaped
3. Create a malicious payload (talk to QA/security team for this if necessary)
4. Note that the malicious payload is escaped
5. prove t/Koha/Plugins/SafeURL.t
6. Celebrate!
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
(cherry picked from commit e8e00cfeb3)
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
parent
fde180efbf
commit
629d2a6f6c
|
|
@ -0,0 +1,66 @@
|
|||
package Koha::Template::Plugin::SafeURL;
|
||||
|
||||
# This file is part of Koha.
|
||||
#
|
||||
# Koha is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Koha is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Koha; if not, see <http://www.gnu.org/licenses>.
|
||||
|
||||
use Modern::Perl;
|
||||
use URI;
|
||||
use base 'Template::Plugin::Filter';
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
my $name = 'safe_url';
|
||||
$self->{_DYNAMIC} = 1;
|
||||
$self->install_filter($name);
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub filter {
|
||||
my ( $self, $text, $args, $config ) = @_;
|
||||
my $uri = URI->new($text);
|
||||
if ($uri) {
|
||||
return $uri;
|
||||
}
|
||||
|
||||
#NOTE: If it isn't a real URL, just return a safe fragment
|
||||
return '#';
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Koha::Template::Plugin::SafeURL - TT Plugin for filtering whole URLs
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
[% USE SafeURL %]
|
||||
|
||||
[% $url | safe_url %]
|
||||
|
||||
This filter parses the text as a URL and returns the object which
|
||||
is stringified in a safe format.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 init
|
||||
|
||||
This method installs the filter name and declares it as a dynamic filter
|
||||
|
||||
=head2 filter
|
||||
|
||||
Returns a stringified version of a Perl URL object
|
||||
|
||||
=cut
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
[% USE TablesSettings %]
|
||||
[% USE AuthorisedValues %]
|
||||
[% USE KohaPlugins %]
|
||||
[% USE SafeURL %]
|
||||
[% SET TagsShowEnabled = ( ( Koha.Preference( 'TagsEnabled' ) == 1 ) && TagsShowOnDetail ) %]
|
||||
[% SET TagsInputEnabled = ( ( Koha.Preference( 'opacuserlogin' ) == 1 ) && ( Koha.Preference( 'TagsEnabled' ) == 1 ) && TagsInputOnDetail ) %]
|
||||
[% SET CoverImagePlugins = KohaPlugins.get_plugins_opac_cover_images %]
|
||||
|
|
@ -1362,14 +1363,14 @@
|
|||
[% IF trackclicks == 'track' || trackclicks == 'anonymous' %]
|
||||
<a target="[% target_attr | html %]" rel="[% rel_attr | html %]" href="/cgi-bin/koha/tracklinks.pl?uri=[% uri | uri %]&biblionumber=[% biblio.biblionumber | html %]&itemnumber=[% ITEM_RESULT.itemnumber | html %]" property="url">[% uri | html %]</a>
|
||||
[% ELSE %]
|
||||
<a target="[% target_attr | html %]" rel="[% rel_attr | html %]" href="[% uri | url %]" property="url">[% uri | html %]</a>
|
||||
<a target="[% target_attr | html %]" rel="[% rel_attr | html %]" href="[% uri | safe_url %]" property="url">[% uri | html %]</a>
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% ELSE %]
|
||||
[% IF trackclicks == 'track' || trackclicks == 'anonymous' %]
|
||||
<a target="[% target_attr | html %]" rel="[% rel_attr | html %]" href="/cgi-bin/koha/tracklinks.pl?uri=[% ITEM_RESULT.uri | uri %]&biblionumber=[% biblio.biblionumber | html %]&itemnumber=[% ITEM_RESULT.itemnumber | html %]" property="url">
|
||||
[% ELSE %]
|
||||
<a target="[% target_attr | html %]" rel="[% rel_attr | html %]" href="[% ITEM_RESULT.uri | url %]" property="url">
|
||||
<a target="[% target_attr | html %]" rel="[% rel_attr | html %]" href="[% ITEM_RESULT.uri | safe_url %]" property="url">
|
||||
[% END %]
|
||||
[% IF Koha.Preference('URLLinkText') %][% Koha.Preference('URLLinkText') | html %][% ELSE %]Link to resource[% END %]
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# This file is part of Koha.
|
||||
#
|
||||
# Koha is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Koha is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Koha; if not, see <http://www.gnu.org/licenses>.
|
||||
|
||||
use Modern::Perl;
|
||||
|
||||
use Test::More tests => 2;
|
||||
use Template;
|
||||
|
||||
subtest 'test double-encoding prevention' => sub {
|
||||
plan tests => 1;
|
||||
my $template = Template->new(
|
||||
{
|
||||
PLUGIN_BASE => 'Koha::Template::Plugin',
|
||||
}
|
||||
);
|
||||
|
||||
my $tt = <<EOF;
|
||||
[%- USE SafeURL %]
|
||||
[%- 'http://koha-community.org?url=https%3A%2F%2Fkoha-community.org' | safe_url -%]
|
||||
EOF
|
||||
|
||||
my $output;
|
||||
$template->process( \$tt, {}, \$output );
|
||||
is( $output, 'http://koha-community.org?url=https%3A%2F%2Fkoha-community.org', 'URL is not double-encoded' );
|
||||
};
|
||||
|
||||
subtest 'double quotes are escaped' => sub {
|
||||
plan tests => 1;
|
||||
my $template = Template->new(
|
||||
{
|
||||
PLUGIN_BASE => 'Koha::Template::Plugin',
|
||||
}
|
||||
);
|
||||
|
||||
my $tt = <<EOF;
|
||||
[%- USE SafeURL %]
|
||||
[%- 'http://koha-community.org?url=https%3A%2F%2Fkoha-community.org"' | safe_url -%]
|
||||
EOF
|
||||
|
||||
my $output;
|
||||
$template->process( \$tt, {}, \$output );
|
||||
is( $output, 'http://koha-community.org?url=https%3A%2F%2Fkoha-community.org%22', 'double quotes are escaped' );
|
||||
};
|
||||
Loading…
Reference in New Issue