8000 Prevent access to external files/URLs via XML entity references. · sureandrew/postgres@a4b0c0a · GitHub
[go: up one dir, main page]

Skip to content

Commit a4b0c0a

Browse files
committed
Prevent access to external files/URLs via XML entity references.
xml_parse() would attempt to fetch external files or URLs as needed to resolve DTD and entity references in an XML value, thus allowing unprivileged database users to attempt to fetch data with the privileges of the database server. While the external data wouldn't get returned directly to the user, portions of it could be exposed in error messages if the data didn't parse as valid XML; and in any case the mere ability to check existence of a file might be useful to an attacker. The ideal solution to this would still allow fetching of references that are listed in the host system's XML catalogs, so that documents can be validated according to installed DTDs. However, doing that with the available libxml2 APIs appears complex and error-prone, so we're not going to risk it in a security patch that necessarily hasn't gotten wide review. So this patch merely shuts off all access, causing any external fetch to silently expand to an empty string. A future patch may improve this. In HEAD and 9.2, also suppress warnings about undefined entities, which would otherwise occur as a result of not loading referenced DTDs. Previous branches don't show such warnings anyway, due to different error handling arrangements. Credit to Noah Misch for first reporting the problem, and for much work towards a solution, though this simplistic approach was not his preference. Also thanks to Daniel Veillard for consultation. Security: CVE-2012-3489
1 parent 8d1f50e commit a4b0c0a

File tree

4 files changed

+68
-0
lines changed

4 files changed

+68
-0
lines changed

src/backend/utils/adt/xml.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#ifdef USE_LIBXML
4949
#include <libxml/chvalid.h>
5050
#include <libxml/parser.h>
51+
#include <libxml/parserInternals.h>
5152
#include <libxml/tree.h>
5253
#include <libxml/uri.h>
5354
#include <libxml/xmlerror.h>
@@ -86,6 +87,8 @@ XmlOptionType xmloption;
8687

8788
static StringInfo xml_err_buf = NULL;
8889

90+
static xmlParserInputPtr xmlPgEntityLoader(const char *URL, const char *ID,
91+
xmlParserCtxtPtr ctxt);
8992
static void xml_errorHandler(void *ctxt, const char *msg,...);
9093
static void xml_ereport_by_code(int level, int sqlcode,
9194
const char *msg, int errcode);
@@ -923,6 +926,9 @@ pg_xml_init(void)
923926
/* Now that xml_err_buf exists, safe to call xml_errorHandler */
924927
xmlSetGenericErrorFunc(NULL, xml_errorHandler);
925928

929+
/* set up our entity loader, too */
930+
xmlSetExternalEntityLoader(xmlPgEntityLoader);
931+
926932
#ifdef USE_LIBXMLCONTEXT
927933
/* Set up memory allocation our way, too */
928934
xml_memory_init();
@@ -947,6 +953,9 @@ pg_xml_init(void)
947953
* about, anyway.
948954
*/
949955
xmlSetGenericErrorFunc(NULL, xml_errorHandler);
956+
957+
/* set up our entity loader, too */
958+
xmlSetExternalEntityLoader(xmlPgEntityLoader);
950959
}
951960
}
952961

@@ -1366,6 +1375,25 @@ xml_pstrdup(const char *string)
13661375
#endif /* USE_LIBXMLCONTEXT */
13671376

13681377

1378+
/*
1379+
* xmlPgEntityLoader --- entity loader callback function
1380+
*
1381+
* Silently prevent any external entity URL from being loaded. We don't want
1382+
* to throw an error, so instead make the entity appear to expand to an empty
1383+
* string.
1384+
*
1385+
* We would prefer to allow loading entities that exist in the system's
1386+
* global XML catalog; but the available libxml2 APIs make that a complex
1387+
* and fragile task. For now, just shut down all external access.
1388+
*/
1389+
static xmlParserInputPtr
1390+
xmlPgEntityLoader(const char *URL, const char *ID,
1391+
xmlParserCtxtPtr ctxt)
1392+
{
1393+
return xmlNewStringInputStream(ctxt, (const xmlChar *) "");
1394+
}
1395+
1396+
13691397
/*
13701398
* xml_ereport --- report an XML-related error
13711399
*

src/test/regress/expected/xml.out

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,3 +467,23 @@ SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
467467
{<b>two</b>,<b>etc</b>}
468468
(1 row)
469469

470+
-- External entity references should not leak filesystem information.
471+
SELECT XMLPARSE(DOCUMENT '<!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/passwd">]><foo>&c;</foo>');
472+
xmlparse
473+
-----------------------------------------------------------------
474+
<!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/passwd">]><foo>&c;</foo>
475+
(1 row)
476+
477+
SELECT XMLPARSE(DOCUMENT '<!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/no.such.file">]><foo>&c;</foo>');
478+
xmlparse
479+
-----------------------------------------------------------------------
480+
<!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/no.such.file">]><foo>&c;</foo>
481+
(1 row)
482+
483+
-- This might or might not load the requested DTD, but it mustn't throw error.
484+
SELECT XMLPARSE(DOCUMENT '<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"><chapter>&nbsp;</chapter>');
485+
xmlparse
486+
------------------------------------------------------------------------------------------------------------------------------------------------------
487+
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"><chapter>&nbsp;</chapter>
488+
(1 row)
489+

src/test/regress/expected/xml_1.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,3 +376,17 @@ SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
376376
ERROR: unsupported XML feature
377377
DETAIL: This functionality requires the server to be built with libxml support.
378378
HINT: You need to rebuild PostgreSQL using --with-libxml.
379+
-- External entity references should not leak filesystem information.
380+
SELECT XMLPARSE(DOCUMENT '<!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/passwd">]><foo>&c;</foo>');
381+
ERROR: unsupported XML feature
382+
DETAIL: This functionality requires the server to be built with libxml support.
383+
HINT: You need to rebuild PostgreSQL using --with-libxml.
384+
SELECT XMLPARSE(DOCUMENT '<!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/no.such.file">]><foo>&c;</foo>');
385+
ERROR: unsupported XML feature
386+
DETAIL: This functionality requires the server to be built with libxml support.
387+
HINT: You need to rebuild PostgreSQL using --with-libxml.
388+
-- This might or might not load the requested DTD, but it mustn't throw error.
389+
SELECT XMLPARSE(DOCUMENT '<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"><chapter>&nbsp;</chapter>');
390+
ERROR: unsupported XML feature
391+
DETAIL: This functionality requires the server to be built with libxml support.
392+
HINT: You need to rebuild PostgreSQL using --with-libxml.

src/test/regress/sql/xml.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,9 @@ SELECT xpath('', '<!-- error -->');
158158
SELECT xpath('//text()', '<local:data xmlns:local="http://127.0.0.1"><local:piece id="1">number one</local:piece><local:piece id="2" /></local:data>');
159159
SELECT xpath('//loc:piece/@id', '<local:data xmlns:local="http://127.0.0.1"><local:piece id="1">number one</local:piece><local:piece id="2" /></local:data>', ARRAY[ARRAY['loc', 'http://127.0.0.1']]);
160160
SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
161+
162+
-- External entity references should not leak filesystem information.
163+
SELECT XMLPARSE(DOCUMENT '<!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/passwd">]><foo>&c;</foo>');
164+
SELECT XMLPARSE(DOCUMENT '<!DOCTYPE foo [<!ENTITY c SYSTEM "/etc/no.such.file">]><foo>&c;</foo>');
165+
-- This might or might not load the requested DTD, but it mustn't throw error.
166+
SELECT XMLPARSE(DOCUMENT '<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"><chapter>&nbsp;</chapter>');

0 commit comments

Comments
 (0)
0