Разъяснения по уязвимостям 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?

много спасибо!

ссылки:

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));

работает просто отлично.