Yesterday, the Sonarsource people disclosed a nice XXE in Wordpress, aka CVE-2021-29447, likely found by the RIPS scanner that they acquired last year.
As explained in their blogpost, the issue was in wp-includes/ID3/getid3.lib.php
:
if (PHP_VERSION_ID < 80000) {
// This function has been deprecated in PHP 8.0 because in libxml 2.9.0, external entity loading is
// disabled by default, so this function is no longer needed to protect against XXE attacks.
$loader = libxml_disable_entity_loader(true);
}
$XMLobject = simplexml_load_string($XMLstring, 'SimpleXMLElement', LIBXML_NOENT);
Plot twist: the LIBEXML_NOENT
doesn't
disable external entities, it means that entities
should be expanded so that no entity nodes should be created inside the parsed
document, which is completely stupid and misleading, especially for a
security-sensitive knob.
Anyway, Snuffleupagus anti-XXE mechanism was supposed to save the day, except it didn't, because as PHP's documentation says:
Disable/enable the ability to load external entities. Note that disabling the loading of external entities may cause general issues with loading XML documents. However, as of libxml 2.9.0 entity substitution is disabled by default, so there is no need to disable the loading of external entities, unless there is the need to resolve internal entity references with
LIBXML_NOENT
.
So it's disabled by default, except when you want to actually use it
explicitly, as discretely highlighted by
PHP's own testsuite.
The proper™ way now being to use
libxml_set_external_entity_loader
instead,
which Snuffleupagus didn't.
Wordpress patched it by invoking libxml_disable_entity_loader
no matter the
PHP version, but if you can't upgrade,
the virtual-patch is simple enough:
sp.disable_function("simplexml_load_string").param("2").value("2").drop();
The next version of Snuffleupagus that should be released at the beginning of May will implement a defence in depth against XXE, mitigating this vulnerability.