summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Martin Szulecki2015-01-23 14:56:59 +0100
committerGravatar Martin Szulecki2015-01-23 14:56:59 +0100
commitc086cb139af7c82845f6d565e636073ff4b37440 (patch)
tree3ef0f3c685237cd537e5407eee1b85139cd84359
parent82a6acc44759a4b0afb8110d682bc32edc1fd602 (diff)
downloadlibplist-c086cb139af7c82845f6d565e636073ff4b37440.tar.gz
libplist-c086cb139af7c82845f6d565e636073ff4b37440.tar.bz2
xplist: Fix limited but possible XXE security vulnerability with XML plists
By using a specifically crafted XML file an attacker could use plistutil to issue a GET request to an arbitrary URL or disclose a local file. The crafted XML file would be using a custom DTD with an external entity reference pointing to the file. Practical abuse is limited but let's still fix it nevertheless. Related to CVE-2013-0339 for libxml2 and CWE-827. Reported by Loïc Bénis from calypt.com. Thanks!
-rw-r--r--src/xplist.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/src/xplist.c b/src/xplist.c
index 4c106aa..2e86ee5 100644
--- a/src/xplist.c
+++ b/src/xplist.c
@@ -29,6 +29,7 @@
#include <inttypes.h>
#include <locale.h>
+#include <libxml/xmlIO.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
@@ -555,11 +556,22 @@ PLIST_API void plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length)
}
}
+static xmlParserInputPtr plist_xml_external_entity_loader(const char *URL, const char *ID, xmlParserCtxtPtr ctxt)
+{
+ return NULL;
+}
+
PLIST_API void plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist)
{
- xmlDocPtr plist_doc = xmlParseMemory(plist_xml, length);
- xmlNodePtr root_node = xmlDocGetRootElement(plist_doc);
+ /* CVE-2013-0339: disable external entity loading to prevent XXE vulnerability */
+ xmlSetExternalEntityLoader(plist_xml_external_entity_loader);
- xml_to_node(root_node, plist);
- xmlFreeDoc(plist_doc);
+ /* read XML from memory and disable network access for security reasons */
+ xmlDocPtr plist_doc = xmlReadMemory(plist_xml, length, "plist_from_xml:memory", NULL, XML_PARSE_NONET);
+ if (plist_doc) {
+ xmlNodePtr root_node = xmlDocGetRootElement(plist_doc);
+
+ xml_to_node(root_node, plist);
+ xmlFreeDoc(plist_doc);
+ }
}