XML не работает с PHP SimpleXMLElement

#php #xml #xml-parsing

Вопрос:

 <?php

$str = <<<XML
<?xml version="1.0"?>
<!DOCTYPE doc [
    <!ENTITY e SYSTEM "/tmp/exp">
]>
<tag>amp;e;</tag>
XML;

$xml = new SimpleXMLElement($str);

echo $xml;

?>
 

Это должно выводить содержимое /tmp/exp , но не выводит, и я не понимаю, почему, даже когда я запускаю сценарий с sudo /tmp/exp правами доступа к файлам или изменяю 777 их на .

Комментарии:

1. Попробуйте передать LIBXML_NOENT в качестве второго аргумента конструктору: 3v4l.org/nTvDp

2. @ChrisHaas Это сработало, спасибо!

3. @ChrisHaas Прежде чем рекомендовать включить эту опцию, вы должны понять, почему она не включена по умолчанию: она связана со многими уязвимостями безопасности, поэтому ее необходимо использовать с осторожностью.

4. @IMSoP, я на 100% согласен, но также кажется, что это может быть то, к чему стремится операция.

5. @ChrisHaas Не обязательно; очевидно, что пример в моем ответе является нереалистично строгим фильтром, но главное, что у вас может быть белый список, из которого должны загружаться объекты — например, вряд ли будет законное использование для загрузки /etc/passwd

Ответ №1:

Загрузка внешних объектов по умолчанию отключена, поскольку это может привести к различным уязвимостям безопасности.

Чтобы безопасно включить его, вам необходимо зарегистрировать пользовательский загрузчик сущностей, который может проверять ожидаемые пути к сущностям и решать, загружать ли их. Например, вы можете разрешить любой файл в определенном каталоге, но не в другом месте на диске — вам, вероятно, не нужно разрешать ссылки на системные файлы, такие как /etc/passwd . Или вы можете сопоставить указанный путь с совершенно другим местоположением в вашей системе.

Затем вам также необходимо предоставить LIBXML_NOENT возможность указать синтаксическому анализатору развернуть объекты с помощью вашего обработчика.

Например:

 libxml_set_external_entity_loader(function($public, $system, $context) {
    if ($system === '/tmp/exp') {
        return fopen('/tmp/exp', 'r');
    }
    else {
        return null;
    }
});
$xml = new SimpleXMLElement($str, LIBXML_NOENT);