Title: Virtual patching CVE-2021-29447 with Snuffleupagus
Date: 2021-04-27 22:30

Yesterday, the [Sonarsource](https://sonarsource.com) people [disclosed a nice XXE
in Wordpress](https://blog.sonarsource.com/wordpress-xxe-security-vulnerability/),
aka [CVE-2021-29447](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-29447),
likely found by the [RIPS](https://en.wikipedia.org/wiki/RIPS) scanner that
they [acquired last year](https://blog.sonarsource.com/sonarsource-acquires-rips-technologies).

As explained in their blogpost, the issue was in `wp-includes/ID3/getid3.lib.php`:

```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`](http://xmlsoft.org/html/libxml-parser.html) 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](https://snuffleupagus.readthedocs.io/features.html#xxe) was supposed
to save the day, except it didn't, because as [PHP's documentation says](https://www.php.net/manual/en/function.libxml-disable-entity-loader.php):

> 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](https://github.com/php/php-src/blob/master/ext/libxml/tests/libxml_entity_loading_disabled_by_default.phpt).
The proper™ way now being to use
[`libxml_set_external_entity_loader`](https://www.php.net/manual/en/function.libxml-set-external-entity-loader.php) 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](https://snuffleupagus.readthedocs.io/features.html#virtual-patching) is simple enough:

```python
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](https://github.com/jvoisin/snuffleupagus/commit/d9cccbbe417d305bb56911cd07a7feac6b89e9a6)
against XXE, mitigating this vulnerability.
