I am parsing XML using SimpleXML in PHP 5 and external entities are not working. The XML parses, but the entities just are blank. The underlying library is libxml2.
This is the code:
libxml_disable_entity_loader(false);
simplexml_load_file($target_file);
It parses the XML as expected, but doesn't resolve the external entities and seems to ignore them.
This is the expected behavior, because you need to tell when loading the document to expand (and therefore remove) these entities:
libxml_disable_entity_loader(false);
simplexml_load_file($target_file, 'SimpleXMLElement', LIBXML_NOENT);
############
This constant is also cross-linked on the manual page of libxml_disable_entity_loader
.
The function itself only enables or disables the default entity loader. Additionally the parser needs to be told via the libxml2 based option flag, that those entities should be substituted. Only then the default loader (or if you have set it to a different one) would kick in.
Online Demo:
<?php
/**
* @link https://stackoverflow.com/a/29864193/367456
*/
$buffer = <<<XML
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "data://text/plain,test" >]><foo>&xxe;</foo>
XML;
libxml_disable_entity_loader(false);
$xml = simplexml_load_string($buffer);
$xml->asXML('php://output');
$xml = simplexml_load_string($buffer, 'SimpleXMLElement', LIBXML_NOENT);
$xml->asXML('php://output');
Output for 5.2.11 - 5.6.8, php7@20140507 - 20150401, hhvm-3.5.0 - 3.6.1
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "data://text/plain,test">
]>
<foo>&xxe;</foo>
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "data://text/plain,test">
]>
<foo>test</foo>
The XML is based on the exploit examples outlined on XML External Entity (XXE) Processing (OWASP Wiki) and modified for the PHP demonstration regarding your question.
And more important than PHP versions is the version of libxml both on system and the binding in PHP. Just saying in case the 3v4l.org demo code creates the impression that it always behaved the same in all PHP versions - this just must not be the case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With