Dear developers and administrators,
the following information may save you some time as it took me a while to figure it out:
Today I noticed some strange issues regarding XML handling in ILIAS with (v5.2.6 2017-07-13, PHP 5.6.31-4+ubuntu16.04.1+deb.sury.org+4). Initially, I discovered a problem in one of my plugins which deals with XML that uses simplexml_load_file() with a local(!) file.
The error message I got from it was:
simplexml_load_file(): I/O warning : failed to load external entity "[MY_FILE]"
I checked everything twice, the 'cwd', the include path, PHP ini settings ... Surprisingly (for me), I was able to read the contents of the XML file one line before I called simplexml_load_file(). Passing the XML string to simplexml_load_string() worked fine.
The error occured randomly (I initially thought), so I really had no idea what could cause that. Then our administrators reported issues when copying/cloning courses via SOAP in customer installations. I exported and imported the course in question as XML into my local installation (which worked fine) and tried to copy the course to reproduce the reported issue afterwards. It worked perfectly with PHP 7.0, but failed with PHP 5.6. The error log contained the same I/O warning mentioned above.
When I added ...
libxml_disable_entity_loader(false);
... in my plugin before using simplexml_load_file() and before the ILIAS SOAP server is instantiated in ./webservice/soap/server.php, the issue seems to be fixed for both cases.
libxml_disable_entity_loader() is not thread safe, so this is the root of all evil (including but not limited to pineapple on pizza).
If ...
libxml_disable_entity_loader(true);
... is called in another script (or another PHP application) and not resetted to false, the problematic state persists globally. There are even some calls of with a boolean true in ILIAS (PHPExcel, SVG Sanitizer), which is dangerous in case an error occured and the state could not be properly resetted to a boolean false.
Best regards, Michael
Am Mittwoch, 16. August 2017 15:13 CEST, Michael Jansen mjansen@databay.de schrieb:
Dear developers and administrators,
the following information may save you some time as it took me a while to figure it out:
Today I noticed some strange issues regarding XML handling in ILIAS with (v5.2.6 2017-07-13, PHP 5.6.31-4+ubuntu16.04.1+deb.sury.org+4). Initially, I discovered a problem in one of my plugins which deals with XML that uses simplexml_load_file() with a local(!) file.
The error message I got from it was:
simplexml_load_file(): I/O warning : failed to load external entity "[MY_FILE]"
Hmm - you should have posted to this list earlier, that one is a really good ol' friend of mine ...
<...>
When I added ...
libxml_disable_entity_loader(false);
... in my plugin before using simplexml_load_file() and before the ILIAS SOAP server is instantiated in ./webservice/soap/server.php, the issue seems to be fixed for both cases.
libxml_disable_entity_loader() is not thread safe, so this is the root of all evil (including but not limited to pineapple on pizza).
To be technically correct, what's bitting you here isn't thread safety (I assume you are not running in a multi-threaded server environment) but global state. As (almost) always, global state is unfortunate.
If ...
libxml_disable_entity_loader(true);
... is called in another script (or another PHP application) and not resetted to false, the problematic state persists globally. There are even some calls of with a boolean true in ILIAS (PHPExcel, SVG Sanitizer), which is dangerous in case an error occured and the state could not be properly resetted to a boolean false.
Yes, that's exactly why global state is so dangerous even in single threaded environments. But, since external entity loading is known as a hard to control entry point for vulnerabilities it actually is a good idea to disable it.
BTW, do you now see why I'm so scared by other global state manipulations (umask, for example)?
Cheers, Ralf Mattes
Hi Ralf,
Am 16.08.2017 um 15:59 schrieb Ralf Mattes:
Am Mittwoch, 16. August 2017 15:13 CEST, Michael Jansen mjansen@databay.de schrieb:
Dear developers and administrators,
the following information may save you some time as it took me a while to figure it out:
Today I noticed some strange issues regarding XML handling in ILIAS with (v5.2.6 2017-07-13, PHP 5.6.31-4+ubuntu16.04.1+deb.sury.org+4). Initially, I discovered a problem in one of my plugins which deals with XML that uses simplexml_load_file() with a local(!) file.
The error message I got from it was:
simplexml_load_file(): I/O warning : failed to load external entity "[MY_FILE]"
Hmm - you should have posted to this list earlier, that one is a really good ol' friend of mine ...
<...>
When I added ...
libxml_disable_entity_loader(false);
... in my plugin before using simplexml_load_file() and before the ILIAS SOAP server is instantiated in ./webservice/soap/server.php, the issue seems to be fixed for both cases.
libxml_disable_entity_loader() is not thread safe, so this is the root of all evil (including but not limited to pineapple on pizza).
To be technically correct, what's bitting you here isn't thread safety (I assume you are not running in a multi-threaded server environment) but global state. As (almost) always, global state is unfortunate.
"thread safe" was not the technically correct term. I noticed this after I pushed the "Send" button in my email client ;-). I just meant: It persists and could be caused by another process.
If ...
libxml_disable_entity_loader(true); ... is called in another script (or another PHP application) and not resetted to false, the problematic state persists globally. There are even some calls of with a boolean true in ILIAS (PHPExcel, SVG Sanitizer), which is dangerous in case an error occured and the state could not be properly resetted to a boolean false.
Yes, that's exactly why global state is so dangerous even in single threaded environments. But, since external entity loading is known as a hard to control entry point for vulnerabilities it actually is a good idea to disable it.
Yes, global state is often evil. Especially, when it is mutated by other libraries/dependencies or even other processes.
BTW, do you now see why I'm so scared by other global state manipulations (umask, for example)?
Cheers, Ralf Mattes
Best regards, Michael