Back-port upstream fix for CVE-2012-3488 (unintended access to libxslt's features for reading/writing external files and URLs). I intentionally did not back-port the part of the patch that disabled reading documents and stylesheets from files/URLs, as that is documented functionality. Upstream removed it because it was broken anyway by their fix for CVE-2012-3489, but that's not a problem in the 8.1 branch, and it seems barely possible that somebody is relying on the functionality. (The security exposure from this is limited anyway, since libxml2 will throw a syntax error unless the referenced file is valid XML.) diff -Naur postgresql-8.1.23.orig/contrib/xml2/expected/xml2.out postgresql-8.1.23/contrib/xml2/expected/xml2.out --- postgresql-8.1.23.orig/contrib/xml2/expected/xml2.out 2010-12-13 22:52:30.000000000 -0500 +++ postgresql-8.1.23/contrib/xml2/expected/xml2.out 2012-08-27 13:32:37.814071837 -0400 @@ -43,8 +43,8 @@ </xsl:template> </xsl:stylesheet> $$::text); - xslt_process ------------------------ + xslt_process +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- <?xml version="1.0"?> <table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> @@ -111,8 +111,8 @@ </xsl:copy> </xsl:template> </xsl:stylesheet>$$); - xslt_process ------------------------ + xslt_process +------------------------------- <?xml version="1.0"?> <aaa/> @@ -126,8 +126,8 @@ </xsl:copy> </xsl:template> </xsl:stylesheet>$$); - xslt_process ------------------------ + xslt_process +------------------------------- <?xml version="1.0"?> <aaa/> @@ -140,3 +140,18 @@ Value</attribute></attributes>'); create index idx_xpath on t1 ( xpath_string ('/attributes/attribute[@name="attr_1"]/text()', xml_data)); +-- possible security exploit +SELECT xslt_process('<xml><foo>Hello from XML</foo></xml>', +$$<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:sax="http://icl.com/saxon" + extension-element-prefixes="sax"> + + <xsl:template match="//foo"> + <sax:output href="0wn3d.txt" method="text"> + <xsl:value-of select="'0wn3d via xml2 extension and libxslt'"/> + <xsl:apply-templates/> + </sax:output> + </xsl:template> +</xsl:stylesheet>$$); +ERROR: failed to apply stylesheet diff -Naur postgresql-8.1.23.orig/contrib/xml2/expected/xml2_1.out postgresql-8.1.23/contrib/xml2/expected/xml2_1.out --- postgresql-8.1.23.orig/contrib/xml2/expected/xml2_1.out 2010-12-13 22:52:30.000000000 -0500 +++ postgresql-8.1.23/contrib/xml2/expected/xml2_1.out 2012-08-27 13:02:58.564088439 -0400 @@ -100,3 +100,18 @@ Value</attribute></attributes>'); create index idx_xpath on t1 ( xpath_string ('/attributes/attribute[@name="attr_1"]/text()', xml_data)); +-- possible security exploit +SELECT xslt_process('<xml><foo>Hello from XML</foo></xml>', +$$<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:sax="http://icl.com/saxon" + extension-element-prefixes="sax"> + + <xsl:template match="//foo"> + <sax:output href="0wn3d.txt" method="text"> + <xsl:value-of select="'0wn3d via xml2 extension and libxslt'"/> + <xsl:apply-templates/> + </sax:output> + </xsl:template> +</xsl:stylesheet>$$); +ERROR: xslt_process() is not available without libxslt diff -Naur postgresql-8.1.23.orig/contrib/xml2/sql/xml2.sql postgresql-8.1.23/contrib/xml2/sql/xml2.sql --- postgresql-8.1.23.orig/contrib/xml2/sql/xml2.sql 2010-12-13 22:52:30.000000000 -0500 +++ postgresql-8.1.23/contrib/xml2/sql/xml2.sql 2012-08-27 13:02:47.068007366 -0400 @@ -92,3 +92,18 @@ create index idx_xpath on t1 ( xpath_string ('/attributes/attribute[@name="attr_1"]/text()', xml_data)); + +-- possible security exploit +SELECT xslt_process('<xml><foo>Hello from XML</foo></xml>', +$$<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:sax="http://icl.com/saxon" + extension-element-prefixes="sax"> + + <xsl:template match="//foo"> + <sax:output href="0wn3d.txt" method="text"> + <xsl:value-of select="'0wn3d via xml2 extension and libxslt'"/> + <xsl:apply-templates/> + </sax:output> + </xsl:template> +</xsl:stylesheet>$$); diff -Naur postgresql-8.1.23.orig/contrib/xml2/xslt_proc.c postgresql-8.1.23/contrib/xml2/xslt_proc.c --- postgresql-8.1.23.orig/contrib/xml2/xslt_proc.c 2010-12-13 22:52:30.000000000 -0500 +++ postgresql-8.1.23/contrib/xml2/xslt_proc.c 2012-08-27 13:31:12.069353774 -0400 @@ -19,6 +19,7 @@ #include <libxslt/xslt.h> #include <libxslt/xsltInternals.h> +#include <libxslt/security.h> #include <libxslt/transform.h> #include <libxslt/xsltutils.h> @@ -56,7 +57,10 @@ xsltStylesheetPtr stylesheet = NULL; xmlDocPtr doctree; xmlDocPtr restree; - xmlDocPtr ssdoc = NULL; + xmlDocPtr ssdoc; + xsltSecurityPrefsPtr xslt_sec_prefs; + bool xslt_sec_prefs_error; + xsltTransformContextPtr xslt_ctxt; xmlChar *resstr; int resstat; int reslen; @@ -87,7 +91,7 @@ if (doctree == NULL) { - elog_error("Error parsing XML document", false); + elog_error("Error parsing XML document", true); PG_RETURN_NULL(); } @@ -100,7 +104,7 @@ if (ssdoc == NULL) { xmlFreeDoc(doctree); - elog_error("Error parsing stylesheet as XML document", false); + elog_error("Error parsing stylesheet as XML document", true); PG_RETURN_NULL(); } @@ -114,16 +118,66 @@ { xmlFreeDoc(doctree); xsltCleanupGlobals(); - elog_error("Failed to parse stylesheet", false); + elog_error("Failed to parse stylesheet", true); + PG_RETURN_NULL(); + } + + xslt_ctxt = xsltNewTransformContext(stylesheet, doctree); + + xslt_sec_prefs_error = false; + if ((xslt_sec_prefs = xsltNewSecurityPrefs()) == NULL) + xslt_sec_prefs_error = true; + + if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_READ_FILE, + xsltSecurityForbid) != 0) + xslt_sec_prefs_error = true; + if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_WRITE_FILE, + xsltSecurityForbid) != 0) + xslt_sec_prefs_error = true; + if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_CREATE_DIRECTORY, + xsltSecurityForbid) != 0) + xslt_sec_prefs_error = true; + if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_READ_NETWORK, + xsltSecurityForbid) != 0) + xslt_sec_prefs_error = true; + if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_WRITE_NETWORK, + xsltSecurityForbid) != 0) + xslt_sec_prefs_error = true; + if (xsltSetCtxtSecurityPrefs(xslt_sec_prefs, xslt_ctxt) != 0) + xslt_sec_prefs_error = true; + + if (xslt_sec_prefs_error) + { + xsltFreeStylesheet(stylesheet); + xmlFreeDoc(doctree); + xsltFreeSecurityPrefs(xslt_sec_prefs); + xsltFreeTransformContext(xslt_ctxt); + xsltCleanupGlobals(); + elog_error("could not set libxslt security preferences", true); + PG_RETURN_NULL(); + } + + restree = xsltApplyStylesheetUser(stylesheet, doctree, params, + NULL, NULL, xslt_ctxt); + + if (restree == NULL) + { + xsltFreeStylesheet(stylesheet); + xmlFreeDoc(doctree); + xsltFreeSecurityPrefs(xslt_sec_prefs); + xsltFreeTransformContext(xslt_ctxt); + xsltCleanupGlobals(); + elog_error("failed to apply stylesheet", true); PG_RETURN_NULL(); } - restree = xsltApplyStylesheet(stylesheet, doctree, params); resstat = xsltSaveResultToString(&resstr, &reslen, restree, stylesheet); xsltFreeStylesheet(stylesheet); xmlFreeDoc(restree); xmlFreeDoc(doctree); + xsltFreeSecurityPrefs(xslt_sec_prefs); + xsltFreeTransformContext(xslt_ctxt); xsltCleanupGlobals();