Bug 23290: XSLT system preferences allow administrators to exploit XML and XSLT vulne...
authorDavid Cook <dcook@prosentient.com.au>
Thu, 23 May 2019 06:53:57 +0000 (16:53 +1000)
committerMartin Renvoize <martin.renvoize@ptfs-europe.com>
Tue, 25 Feb 2020 13:40:48 +0000 (13:40 +0000)
The problem is that administrators can provide XSLTs that
can read from the server and network and write to the server. The

This patch prevents the Koha::XSLT_Handler from running
XSLT stylesheets that call actions such as read_file, write_file,
read_net, and write_net as documented at
https://metacpan.org/pod/XML::LibXSLT#XML::LibXSLT::Security

(Previous tests suggested issues with XML external entities
causing read file like vulnerabilities but these were not
reproducible)

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>

Koha/XSLT_Handler.pm

index 7a51188..2868ea0 100644 (file)
@@ -318,8 +318,41 @@ sub _load {
         return;
     }
 
+    my $security = XML::LibXSLT::Security->new();
+    $security->register_callback( read_file  => sub {
+        warn "read_file called in XML::LibXSLT";
+        #i.e. when using the exsl:document() element or document() function (to read a XML file)
+        my ($tctxt,$value) = @_;
+        return 0;
+    });
+    $security->register_callback( write_file => sub {
+        warn "write_file called in XML::LibXSLT";
+        #i.e. when using the exsl:document element (or document() function?) (to write an output file of many possible types)
+        #e.g.
+        #<exsl:document href="file:///tmp/breached.txt">
+        #   <xsl:text>breached!</xsl:text>
+        #</exsl:document>
+        my ($tctxt,$value) = @_;
+        return 0;
+    });
+    $security->register_callback( read_net   => sub {
+        warn "read_net called in XML::LibXSLT";
+        #i.e. when using the document() function (to read XML from the network)
+        #e.g. <xsl:copy-of select="document('http://localhost')" />
+        my ($tctxt,$value) = @_;
+        return 0;
+    });
+    $security->register_callback( write_net  => sub {
+        warn "write_net called in XML::LibXSLT";
+        #NOTE: it's unknown how one would invoke this, but covering our bases anyway
+        my ($tctxt,$value) = @_;
+        return 0;
+    });
+
     #parse sheet
     my $xslt = XML::LibXSLT->new;
+    $xslt->security_callbacks( $security );
+
     $rv = $code? $digest.$codelen: $filename;
     $self->{xslt_hash}->{$rv} = eval { $xslt->parse_stylesheet($style_doc) };
     if ($@) {