Разъяснения по уязвимостям XXE во всех версиях PHP
Я размещаю вопрос здесь в крайнем случае, я просмотрел интернет и прошел через множество попыток, но не преуспел.
репликация атаки XXE-это то, что я пытаюсь сделать, чтобы предотвратить их, но я не могу понять, как PHP работает с XML-сущностями. Для записи я использую PHP 5.5.10 на Ubuntu 12.04, но я сделал некоторые тесты на 5.4 и 5.3, а libxml2, похоже, имеет версию 2.7.8 (которая, похоже, не включает значение по умолчанию для не разрешения сущности.)
в следующем примере вызов libxml_disable_entity_loader () с true или false не имеет никакого эффекта, или я делаю что-то неправильно.
$xml = <<<XML
<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY c PUBLIC "bar" "/etc/passwd">
]>
<root>
<test>Test</test>
<sub>&c;</sub>
</root>
XML;
libxml_disable_entity_loader(true);
$dom = new DOMDocument();
$dom->loadXML($xml);
// Prints Test.
print $dom->textContent;
но я мог бы специально передать некоторые аргументы loadXML (), чтобы разрешить некоторые параметры, и это работает, когда сущность является локальным файлом, а не когда это внешний URL.
$xml = <<<XML
<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY c PUBLIC "bar" "/etc/passwd">
]>
<root>
<test>Test</test>
<sub>&c;</sub>
</root>
XML;
$dom = new DOMDocument();
$dom->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD);
// Prints Test.
print $dom->textContent;
Теперь, если мы меняем сущность на что - то другое, как в следующем примере, сущность разрешена, но я не мог отключите его вообще, используя параметры или функции... Что происходит?!
$xml = <<<XML
<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY c "Blah blah">
]>
<root>
<test>Test</test>
<sub>&c;</sub>
</root>
XML;
$dom = new DOMDocument();
$dom->loadXML($xml);
// Prints Test.
print $dom->textContent;
единственный способ, который я мог найти, - перезаписать свойства объекта DOMDocument.
- resolveExternals установлено в 1
- substituteEntities установить в 1
тогда они разрешены или нет.
Итак, подводя итог, я действительно хотел бы понять, что я, очевидно, не понимаю . Почему эти параметры и функции кажется, никакого эффекта? Имеет ли libxml2 приоритет над PHP?
много спасибо!
ссылки:
- https://www.owasp.org/index.php/XML_External_Entity_%28XXE%29_Processing
- http://au2.php.net/libxml_disable_entity_loader
- http://au2.php.net/manual/en/libxml.constants.php
- http://www.vsecurity.com/download/papers/XMLDTDEntityAttacks.pdf
- http://www.mediawiki.org/wiki/XML_External_Entity_Processing
- как могу ли я использовать различные XML-библиотеки PHP, чтобы получить функциональность DOM-like и избежать уязвимостей DoS, таких как миллиард смеха или квадратичный взрыв?
1 ответов
сохраняя при этом его простым .. Как должно быть просто: -)
ваш первый фрагмент кода
libxml_disable_entity_loader
делает или не делает ничего здесь, основываясь на том, разрешает ли ваша система сущности по умолчанию или нет (моя нет). Это контролируется LIBXML_NOENT
опция libxml.
без него обработчик документов может даже не пытаться переводить внешние объекты и, следовательно,libxml_disable_entity_loader
не имеет ничего, чтобы действительно повлиять (если libxml не загружает сущности по умолчанию что, похоже, имеет место в вашем тестовом примере).
добавить LIBXML_NOENT
to loadXML()
такой:
$dom->loadXML($xml, LIBXML_NOENT);
и вы быстро получите:
PHP Warning: DOMDocument::loadXML(): I/O warning : failed to load external entity "/etc/passwd" in ...
PHP Warning: DOMDocument::loadXML(): Failure to process entity c in Entity, line: 7 in ...
PHP Warning: DOMDocument::loadXML(): Entity 'c' not defined in Entity, line: 7 in ...
ваш второй фрагмент кода
в этом сценарии вы включили разрешение сущности с помощью , вот почему он идет после /etc/passwd
.
пример отлично работает на моей машине даже для внешнего URL - адреса-я изменил ENTITY
на внешний, как это:
<!ENTITY c PUBLIC "bar" "https://stackoverflow.com/opensearch.xml">
это может, однако, быть даже под влиянием, например. allow_url_fopen
PHP ini setting-поместите его в false, и PHP никогда не будет загружать удаленный файл.
третий фрагмент кода
XML-объект, который вы предоставили, не является внешним, а скорее внутренним (см., например. здесь).
сущности:
<!ENTITY c "Blah blah">
как определяется внутренняя сущность:
<!ENTITY % name "entity_value">
поэтому нет причин для PHP или libxml, чтобы предотвратить разрешение такой сущности.
вывод
я быстро поставил PHP XXE тестер скрипт который пробует различные настройки и показывает, является ли XXE успешным и в каком случае.
единственная строка, которая должна фактически показывать предупреждение, - это "LIBXML_NOENT".
если какая-либо другая строка загружает WARNING, external entity loaded!
ваша настройка позволяет загружать внешние объекты по умолчанию.
вы не может пойти не так, используя следует использовать libxml_disable_entity_loader () независимо от настроек вашего/вашего провайдера по умолчанию. Если ваше приложение когда-либо будет перенесено, оно может мгновенно стать уязвимым.
правильное использование
как утверждает MediaWiki в ссылка, которую вы опубликовали.
к сожалению, способ, которым libxml2 реализует отключение, библиотека калечится, когда внешние объекты отключены, и функции, которые в противном случае были бы безопасными, вызывают исключение во всем синтаксическом анализе.
$oldValue = libxml_disable_entity_loader(true);
// do whatever XML-processing related
libxml_disable_entity_loader($oldValue);
Примечание: libxml_disable_entity_loader () также запрещает загрузку внешних xml-файлов напрямую (не через сущности):
<?php
$remote_xml = "https://stackoverflow.com/opensearch.xml";
$dom = new DOMDocument();
if ($dom->load($remote_xml) !== FALSE)
echo "loaded remote xml!\n";
else
echo "failed to load remote xml!\n";
libxml_disable_entity_loader(true);
if ($dom->load($remote_xml) !== FALSE)
echo "loaded remote xml after libxml_disable_entity_loader(true)!\n";
else
echo "failed to remote xml after libxml_disable_entity_loader(true)!\n";
на моей машине:
loaded remote xml!
PHP Warning: DOMDocument::load(): I/O warning : failed to load external entity "https://stackoverflow.com/opensearch.xml" in ...
failed to remote xml after libxml_disable_entity_loader(true)!
возможно, это связано с эта ошибка PHP но PHP действительно глупо об этом, как:
libxml_disable_entity_loader(true);
$dom->loadXML(file_get_contents($remote_xml));
работает просто отлично.