XXE (XML External Entity) - атака через XML з визначенням зовнішньої сутності, яка вказує на файл чи URL. Парсер, що підставляє такі сутності, вставляє в документ вміст файлу сервера чи відповідь внутрішнього сервісу.
<?xml version="1.0"?>
<!DOCTYPE order [
<!ENTITY secret SYSTEM "file:///var/www/app/.env">
]>
<order><comment>&secret;</comment></order>
Якщо застосунок потім показує чи зберігає comment - зловмисник отримує вміст .env. Варіанти - SSRF через http:// у сутності, «сліпий» XXE з передачею даних на зовнішній сервер, DoS «мільярдом сміхів» (експоненційно вкладені сутності).
Де трапляється XML: імпорт прайсів і фідів, SOAP-інтеграції, SAML (вхід через корпоративний SSO), формати Office (DOCX, XLSX - це zip з XML), SVG.
Сучасний PHP за замовчуванням безпечніший. З libxml 2.9 зовнішні сутності не підставляються, якщо їх не ввімкнути явно. Небезпечні - прапорці:
$doc = new DOMDocument();
$doc->loadXML($xml); // за замовчуванням сутності не розкриваються
$doc->loadXML($xml, LIBXML_NOENT); // НЕБЕЗПЕЧНО: розкриває сутності, зокрема зовнішні
$doc->loadXML($xml, LIBXML_DTDLOAD); // НЕБЕЗПЕЧНО: завантажує зовнішні DTD
Назва LIBXML_NOENT вводить в оману: «no entities» означає «замінити сутності їхнім вмістом», тобто ввімкнути підстановку. Його часто додають «щоб працювали &-подібні сутності» - і відкривають XXE.
Функцію libxml_disable_entity_loader() оголошено застарілою в PHP 8.0 - вона більше не потрібна для захисту за замовчуванням.
Правила:
- не використовувати
LIBXML_NOENTіLIBXML_DTDLOADз даними ззовні; - відхиляти документи з
<!DOCTYPE>, якщо формату він не потрібен; - обмежувати розмір XML і глибину вкладеності;
- бібліотеки для SAML і SOAP - актуальні версії: XXE в них - відомий клас вразливостей;
- SVG від користувачів - окрема тема: окрім XXE під час обробки на сервері, SVG може містити скрипти (XSS при відкритті).
JSON замість XML, де це можливо, - менше поверхня атаки: у JSON немає сутностей і DTD.