php如何禁止外部实体引用,防止XXE
創建於:2025年10月17日
使用 GPT-5 Thinking 回答 Chat01
創建於:2025年10月17日
使用 GPT-5 Thinking 回答 Chat01
php如何禁止外部实体引用,防止XXE
下面给你一份「XXE 防护速查表」,覆盖 PHP 里最常见的 XML 解析方式(DOMDocument / SimpleXML / XMLReader)以及历史兼容点。
<!DOCTYPE
直接拒绝。LIBXML_NONET
,阻止加载远程实体/外部 DTD。LIBXML_NOENT
(它会展开实体,存在风险)。LIBXML_DTDLOAD
/ LIBXML_DTDATTR
,也不要验证解析时加载外部资源。libxml_disable_entity_loader
:它已废弃并基本不再生效;现代 libxml 默认已禁用外部实体加载。phpfunction dom_load_xml_safe(string $xml): DOMDocument { // 1) 直接拒绝带 DOCTYPE 的 XML(最稳妥) if (stripos($xml, '<!DOCTYPE') !== false) { throw new RuntimeException('DTD/DOCTYPE 不允许,已拒绝解析。'); } libxml_use_internal_errors(true); // 捕获解析错误,不向外输出 $dom = new DOMDocument(); // 显式关闭这些行为(默认就是 false,这里再次强调) $dom->resolveExternals = false; // 不解析外部实体 $dom->substituteEntities = false; // 不展开实体 $dom->validateOnParse = false; // 不在解析时做验证(会触发外部访问) // 2) 禁止网络访问 + 抑制警告 $options = LIBXML_NONET | LIBXML_NOERROR | LIBXML_NOWARNING; if (!$dom->loadXML($xml, $options)) { throw new RuntimeException('XML 无效或解析失败。'); } return $dom; }
php$dom = new DOMDocument(); $dom->resolveExternals = false; $dom->substituteEntities = false; $dom->validateOnParse = false; $dom->load('/path/local.xml', LIBXML_NONET | LIBXML_NOERROR | LIBXML_NOWARNING);
phpfunction simplexml_load_string_safe(string $xml): SimpleXMLElement { if (stripos($xml, '<!DOCTYPE') !== false) { throw new RuntimeException('DTD/DOCTYPE 不允许。'); } libxml_use_internal_errors(true); $options = LIBXML_NONET | LIBXML_NOERROR | LIBXML_NOWARNING; $sx = simplexml_load_string($xml, 'SimpleXMLElement', $options); if ($sx === false) { throw new RuntimeException('XML 无效或解析失败。'); } return $sx; }
php$reader = new XMLReader(); // 禁网 $reader->XML($xml, null, LIBXML_NONET); // 明确关闭 DTD 加载 / 实体替换 / 验证 $reader->setParserProperty(XMLReader::LOADDTD, false); $reader->setParserProperty(XMLReader::SUBST_ENTITIES, false); $reader->setParserProperty(XMLReader::VALIDATE, false); // 开始读取 while ($reader->read()) { // ... } $reader->close();
php$prev = libxml_disable_entity_loader(true); // 解析... libxml_disable_entity_loader($prev);
LIBXML_NOENT
或加载 DTD,需检查其解析选项。LIBXML_NOENT
(会展开实体,易被 XXE 利用)LIBXML_DTDLOAD
/ LIBXML_DTDATTR
(会加载/处理 DTD)validateOnParse = true
常导致外部访问)按上面的模板处理,基本就能禁止外部实体引用并防止 XXE。如果你贴一下现在的解析代码,我可以直接帮你改成安全版本。