aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/xml2/expected/xml2.out15
-rw-r--r--contrib/xml2/expected/xml2_1.out15
-rw-r--r--contrib/xml2/sql/xml2.sql15
-rw-r--r--contrib/xml2/xslt_proc.c70
-rw-r--r--doc/src/sgml/xml2.sgml8
5 files changed, 97 insertions, 26 deletions
diff --git a/contrib/xml2/expected/xml2.out b/contrib/xml2/expected/xml2.out
index 3bf676fb400..eba6ae60364 100644
--- a/contrib/xml2/expected/xml2.out
+++ b/contrib/xml2/expected/xml2.out
@@ -207,3 +207,18 @@ SELECT xslt_process('<employee><name>cim</name><age>30</age><pay>400</pay></empl
(1 row)
+-- 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 --git a/contrib/xml2/expected/xml2_1.out b/contrib/xml2/expected/xml2_1.out
index fda626e08c7..bac90e5a2a9 100644
--- a/contrib/xml2/expected/xml2_1.out
+++ b/contrib/xml2/expected/xml2_1.out
@@ -151,3 +151,18 @@ SELECT xslt_process('<employee><name>cim</name><age>30</age><pay>400</pay></empl
</xsl:template>
</xsl:stylesheet>$$::text, 'n1="v1",n2="v2",n3="v3",n4="v4",n5="v5",n6="v6",n7="v7",n8="v8",n9="v9",n10="v10",n11="v11",n12="v12"'::text);
ERROR: xslt_process() is not available without libxslt
+-- 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 --git a/contrib/xml2/sql/xml2.sql b/contrib/xml2/sql/xml2.sql
index 4a996af7167..ac49cfa7c52 100644
--- a/contrib/xml2/sql/xml2.sql
+++ b/contrib/xml2/sql/xml2.sql
@@ -122,3 +122,18 @@ SELECT xslt_process('<employee><name>cim</name><age>30</age><pay>400</pay></empl
</xsl:element>
</xsl:template>
</xsl:stylesheet>$$::text, 'n1="v1",n2="v2",n3="v3",n4="v4",n5="v5",n6="v6",n7="v7",n8="v8",n9="v9",n10="v10",n11="v11",n12="v12"'::text);
+
+-- 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 --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c
index a93931d2618..2f24b39bcc0 100644
--- a/contrib/xml2/xslt_proc.c
+++ b/contrib/xml2/xslt_proc.c
@@ -26,6 +26,7 @@
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
+#include <libxslt/security.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#endif /* USE_LIBXSLT */
@@ -61,7 +62,8 @@ xslt_process(PG_FUNCTION_ARGS)
volatile xsltStylesheetPtr stylesheet = NULL;
volatile xmlDocPtr doctree = NULL;
volatile xmlDocPtr restree = NULL;
- volatile xmlDocPtr ssdoc = NULL;
+ volatile xsltSecurityPrefsPtr xslt_sec_prefs = NULL;
+ volatile xsltTransformContextPtr xslt_ctxt = NULL;
volatile int resstat = -1;
xmlChar *resstr = NULL;
int reslen = 0;
@@ -83,36 +85,62 @@ xslt_process(PG_FUNCTION_ARGS)
PG_TRY();
{
- /* Check to see if document is a file or a literal */
+ xmlDocPtr ssdoc;
+ bool xslt_sec_prefs_error;
- if (VARDATA(doct)[0] == '<')
- doctree = xmlParseMemory((char *) VARDATA(doct), VARSIZE(doct) - VARHDRSZ);
- else
- doctree = xmlParseFile(text_to_cstring(doct));
+ /* Parse document */
+ doctree = xmlParseMemory((char *) VARDATA(doct),
+ VARSIZE(doct) - VARHDRSZ);
if (doctree == NULL)
xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
"error parsing XML document");
/* Same for stylesheet */
- if (VARDATA(ssheet)[0] == '<')
- {
- ssdoc = xmlParseMemory((char *) VARDATA(ssheet),
- VARSIZE(ssheet) - VARHDRSZ);
- if (ssdoc == NULL)
- xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
- "error parsing stylesheet as XML document");
+ ssdoc = xmlParseMemory((char *) VARDATA(ssheet),
+ VARSIZE(ssheet) - VARHDRSZ);
- stylesheet = xsltParseStylesheetDoc(ssdoc);
- }
- else
- stylesheet = xsltParseStylesheetFile((xmlChar *) text_to_cstring(ssheet));
+ if (ssdoc == NULL)
+ xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
+ "error parsing stylesheet as XML document");
+
+ /* After this call we need not free ssdoc separately */
+ stylesheet = xsltParseStylesheetDoc(ssdoc);
if (stylesheet == NULL)
xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
"failed to parse stylesheet");
- restree = xsltApplyStylesheet(stylesheet, doctree, params);
+ 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)
+ ereport(ERROR,
+ (errmsg("could not set libxslt security preferences")));
+
+ restree = xsltApplyStylesheetUser(stylesheet, doctree, params,
+ NULL, NULL, xslt_ctxt);
if (restree == NULL)
xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
@@ -128,6 +156,10 @@ xslt_process(PG_FUNCTION_ARGS)
xmlFreeDoc(restree);
if (doctree != NULL)
xmlFreeDoc(doctree);
+ if (xslt_sec_prefs != NULL)
+ xsltFreeSecurityPrefs(xslt_sec_prefs);
+ if (xslt_ctxt != NULL)
+ xsltFreeTransformContext(xslt_ctxt);
xsltCleanupGlobals();
pg_xml_done(xmlerrcxt, true);
@@ -139,6 +171,8 @@ xslt_process(PG_FUNCTION_ARGS)
xsltFreeStylesheet(stylesheet);
xmlFreeDoc(restree);
xmlFreeDoc(doctree);
+ xsltFreeSecurityPrefs(xslt_sec_prefs);
+ xsltFreeTransformContext(xslt_ctxt);
xsltCleanupGlobals();
pg_xml_done(xmlerrcxt, false);
diff --git a/doc/src/sgml/xml2.sgml b/doc/src/sgml/xml2.sgml
index 47bac31f0c7..ce5a2f0645b 100644
--- a/doc/src/sgml/xml2.sgml
+++ b/doc/src/sgml/xml2.sgml
@@ -437,14 +437,6 @@ xslt_process(text document, text stylesheet, text paramlist) returns text
</para>
<para>
- Also note that if either the document or stylesheet values do not
- begin with a &lt; then they will be treated as URLs and libxslt will
- fetch them. It follows that you can use <function>xslt_process</> as a
- means to fetch the contents of URLs &mdash; you should be aware of the
- security implications of this.
- </para>
-
- <para>
There is also a two-parameter version of <function>xslt_process</> which
does not pass any parameters to the transformation.
</para>