Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit adc97d0

Browse files
committed
Prevent access to external files/URLs via contrib/xml2's xslt_process().
libxslt offers the ability to read and write both files and URLs through stylesheet commands, thus allowing unprivileged database users to both read and write data with the privileges of the database server. Disable that through proper use of libxslt's security options. Also, remove xslt_process()'s ability to fetch documents and stylesheets from external files/URLs. While this was a documented "feature", it was long regarded as a terrible idea. The fix for CVE-2012-3489 broke that capability, and rather than expend effort on trying to fix it, we're just going to summarily remove it. While the ability to write as well as read makes this security hole considerably worse than CVE-2012-3489, the problem is mitigated by the fact that xslt_process() is not available unless contrib/xml2 is installed, and the longstanding warnings about security risks from that should have discouraged prudent DBAs from installing it in security-exposed databases. Reported and fixed by Peter Eisentraut. Security: CVE-2012-3488
1 parent 17351fc commit adc97d0

File tree

5 files changed

+97
-26
lines changed

5 files changed

+97
-26
lines changed

contrib/xml2/expected/xml2.out

+15
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,18 @@ SELECT xslt_process('<employee><name>cim</name><age>30</age><pay>400</pay></empl
207207

208208
(1 row)
209209

210+
-- possible security exploit
211+
SELECT xslt_process('<xml><foo>Hello from XML</foo></xml>',
212+
$$<xsl:stylesheet version="1.0"
213+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
214+
xmlns:sax="http://icl.com/saxon"
215+
extension-element-prefixes="sax">
216+
217+
<xsl:template match="//foo">
218+
<sax:output href="0wn3d.txt" method="text">
219+
<xsl:value-of select="'0wn3d via xml2 extension and libxslt'"/>
220+
<xsl:apply-templates/>
221+
</sax:output>
222+
</xsl:template>
223+
</xsl:stylesheet>$$);
224+
ERROR: failed to apply stylesheet

contrib/xml2/expected/xml2_1.out

+15
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,18 @@ SELECT xslt_process('<employee><name>cim</name><age>30</age><pay>400</pay></empl
151151
</xsl:template>
152152
</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);
153153
ERROR: xslt_process() is not available without libxslt
154+
-- possible security exploit
155+
SELECT xslt_process('<xml><foo>Hello from XML</foo></xml>',
156+
$$<xsl:stylesheet version="1.0"
157+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
158+
xmlns:sax="http://icl.com/saxon"
159+
extension-element-prefixes="sax">
160+
161+
<xsl:template match="//foo">
162+
<sax:output href="0wn3d.txt" method="text">
163+
<xsl:value-of select="'0wn3d via xml2 extension and libxslt'"/>
164+
<xsl:apply-templates/>
165+
</sax:output>
166+
</xsl:template>
167+
</xsl:stylesheet>$$);
168+
ERROR: xslt_process() is not available without libxslt

contrib/xml2/sql/xml2.sql

+15
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,18 @@ SELECT xslt_process('<employee><name>cim</name><age>30</age><pay>400</pay></empl
122122
</xsl:element>
123123
</xsl:template>
124124
</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);
125+
126+
-- possible security exploit
127+
SELECT xslt_process('<xml><foo>Hello from XML</foo></xml>',
128+
$$<xsl:stylesheet version="1.0"
129+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
130+
xmlns:sax="http://icl.com/saxon"
131+
extension-element-prefixes="sax">
132+
133+
<xsl:template match="//foo">
134+
<sax:output href="0wn3d.txt" method="text">
135+
<xsl:value-of select="'0wn3d via xml2 extension and libxslt'"/>
136+
<xsl:apply-templates/>
137+
</sax:output>
138+
</xsl:template>
139+
</xsl:stylesheet>$$);

contrib/xml2/xslt_proc.c

+52-18
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <libxslt/xslt.h>
2828
#include <libxslt/xsltInternals.h>
29+
#include <libxslt/security.h>
2930
#include <libxslt/transform.h>
3031
#include <libxslt/xsltutils.h>
3132
#endif /* USE_LIBXSLT */
@@ -61,7 +62,8 @@ xslt_process(PG_FUNCTION_ARGS)
6162
volatile xsltStylesheetPtr stylesheet = NULL;
6263
volatile xmlDocPtr doctree = NULL;
6364
volatile xmlDocPtr restree = NULL;
64-
volatile xmlDocPtr ssdoc = NULL;
65+
volatile xsltSecurityPrefsPtr xslt_sec_prefs = NULL;
66+
volatile xsltTransformContextPtr xslt_ctxt = NULL;
6567
volatile int resstat = -1;
6668
xmlChar *resstr = NULL;
6769
int reslen = 0;
@@ -83,36 +85,62 @@ xslt_process(PG_FUNCTION_ARGS)
8385

8486
PG_TRY();
8587
{
86-
/* Check to see if document is a file or a literal */
88+
xmlDocPtr ssdoc;
89+
bool xslt_sec_prefs_error;
8790

88-
if (VARDATA(doct)[0] == '<')
89-
doctree = xmlParseMemory((char *) VARDATA(doct), VARSIZE(doct) - VARHDRSZ);
90-
else
91-
doctree = xmlParseFile(text_to_cstring(doct));
91+
/* Parse document */
92+
doctree = xmlParseMemory((char *) VARDATA(doct),
93+
VARSIZE(doct) - VARHDRSZ);
9294

9395
if (doctree == NULL)
9496
xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
9597
"error parsing XML document");
9698

9799
/* Same for stylesheet */
98-
if (VARDATA(ssheet)[0] == '<')
99-
{
100-
ssdoc = xmlParseMemory((char *) VARDATA(ssheet),
101-
VARSIZE(ssheet) - VARHDRSZ);
102-
if (ssdoc == NULL)
103-
xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
104-
"error parsing stylesheet as XML document");
100+
ssdoc = xmlParseMemory((char *) VARDATA(ssheet),
101+
VARSIZE(ssheet) - VARHDRSZ);
105102

106-
stylesheet = xsltParseStylesheetDoc(ssdoc);
107-
}
108-
else
109-
stylesheet = xsltParseStylesheetFile((xmlChar *) text_to_cstring(ssheet));
103+
if (ssdoc == NULL)
104+
xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
105+
"error parsing stylesheet as XML document");
106+
107+
/* After this call we need not free ssdoc separately */
108+
stylesheet = xsltParseStylesheetDoc(ssdoc);
110109

111110
if (stylesheet == NULL)
112111
xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
113112
"failed to parse stylesheet");
114113

115-
restree = xsltApplyStylesheet(stylesheet, doctree, params);
114+
xslt_ctxt = xsltNewTransformContext(stylesheet, doctree);
115+
116+
xslt_sec_prefs_error = false;
117+
if ((xslt_sec_prefs = xsltNewSecurityPrefs()) == NULL)
118+
xslt_sec_prefs_error = true;
119+
120+
if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_READ_FILE,
121+
xsltSecurityForbid) != 0)
122+
xslt_sec_prefs_error = true;
123+
if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_WRITE_FILE,
124+
xsltSecurityForbid) != 0)
125+
xslt_sec_prefs_error = true;
126+
if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_CREATE_DIRECTORY,
127+
xsltSecurityForbid) != 0)
128+
xslt_sec_prefs_error = true;
129+
if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_READ_NETWORK,
130+
xsltSecurityForbid) != 0)
131+
xslt_sec_prefs_error = true;
132+
if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_WRITE_NETWORK,
133+
xsltSecurityForbid) != 0)
134+
xslt_sec_prefs_error = true;
135+
if (xsltSetCtxtSecurityPrefs(xslt_sec_prefs, xslt_ctxt) != 0)
136+
xslt_sec_prefs_error = true;
137+
138+
if (xslt_sec_prefs_error)
139+
ereport(ERROR,
140+
(errmsg("could not set libxslt security preferences")));
141+
142+
restree = xsltApplyStylesheetUser(stylesheet, doctree, params,
143+
NULL, NULL, xslt_ctxt);
116144

117145
if (restree == NULL)
118146
xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
@@ -128,6 +156,10 @@ xslt_process(PG_FUNCTION_ARGS)
128156
xmlFreeDoc(restree);
129157
if (doctree != NULL)
130158
xmlFreeDoc(doctree);
159+
if (xslt_sec_prefs != NULL)
160+
xsltFreeSecurityPrefs(xslt_sec_prefs);
161+
if (xslt_ctxt != NULL)
162+
xsltFreeTransformContext(xslt_ctxt);
131163
xsltCleanupGlobals();
132164

133165
pg_xml_done(xmlerrcxt, true);
@@ -139,6 +171,8 @@ xslt_process(PG_FUNCTION_ARGS)
139171
xsltFreeStylesheet(stylesheet);
140172
xmlFreeDoc(restree);
141173
xmlFreeDoc(doctree);
174+
xsltFreeSecurityPrefs(xslt_sec_prefs);
175+
xsltFreeTransformContext(xslt_ctxt);
142176
xsltCleanupGlobals();
143177

144178
pg_xml_done(xmlerrcxt, false);

doc/src/sgml/xml2.sgml

-8
Original file line numberDiff line numberDiff line change
@@ -436,14 +436,6 @@ xslt_process(text document, text stylesheet, text paramlist) returns text
436436
contain commas!
437437
</para>
438438

439-
<para>
440-
Also note that if either the document or stylesheet values do not
441-
begin with a &lt; then they will be treated as URLs and libxslt will
442-
fetch them. It follows that you can use <function>xslt_process</> as a
443-
means to fetch the contents of URLs &mdash; you should be aware of the
444-
security implications of this.
445-
</para>
446-
447439
<para>
448440
There is also a two-parameter version of <function>xslt_process</> which
449441
does not pass any parameters to the transformation.

0 commit comments

Comments
 (0)