从 libxml 2.9 开始,解析 XML 时已禁用加载外部实体,以防止XXE 攻击 http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html.
在这种情况下,为了能够在使用 PHP 的 DOMDocument 解析 XML 时加载 DTD 文件,LIBXML_DTDLOAD
必须指定。
有什么好方法来验证这一点only在启用之前将加载预期的 DTDLIBXML_DTDLOAD
?
我能想到的一种方法(如下面的示例代码所示)是禁用实体加载,解析 XML 文件一次,检查 DOCTYPE 声明是否符合预期,然后在启用实体加载的情况下再次解析 XML。这样就足够了吗?
<?php
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.0 20120330//EN" "http://jats.nlm.nih.gov/publishing/1.0/JATS-journalpublishing1.dtd">
<article/>
XML;
// entity loading disabled
libxml_disable_entity_loader();
$doc = new DOMDocument;
$doc->loadXML($xml, LIBXML_DTDLOAD); // PHP Warning: DOMDocument::load(): I/O warning : failed to load external entity
print $doc->doctype->systemId; // http://jats.nlm.nih.gov/publishing/1.0/JATS-journalpublishing1.dtd
// entity loading enabled
libxml_disable_entity_loader(false);
$doc = new DOMDocument;
$doc->loadXML($xml, LIBXML_DTDLOAD);
print $doc->doctype->systemId; // http://jats.nlm.nih.gov/publishing/1.0/JATS-journalpublishing1.dtd
在启用之前验证是否仅加载预期的 DTD 的好方法是什么LIBXML_DTDLOAD
?
如果您想过滤(白名单)预期的 DTD,您可以通过返回禁用所有其他 DTD 来实现NULL
从你自己的callable已被设置为外部实体加载器 via libxml_set_external_entity_loader http://php.net/libxml_set_external_entity_loader.
也就是说,您将使用LIBXML_DTDLOAD
标记,然后解析为资源句柄 http://php.net/fopen在您的函数中,以防 DTD 被列入白名单。如果没有,你返回说NULL http://php.net/null.
<?php
/**
* @link http://stackoverflow.com/q/24526493/367456
*/
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.0 20120330//EN" "http://jats.nlm.nih.gov/publishing/1.0/JATS-journalpublishing1.dtd">
<article/>
XML;
/* own entity loader */
libxml_set_external_entity_loader(function() {
var_dump(func_get_args()); // just for demonstrating purposes
return NULL;
});
$doc = new DOMDocument;
$doc->loadXML($xml, LIBXML_DTDLOAD);
echo "----\n";
/* restore default entity loader */
libxml_set_external_entity_loader(NULL);
$doc = new DOMDocument;
$doc->loadXML($xml, LIBXML_DTDLOAD);
输出示例:
array(3) {
[0]=>
string(66) "-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.0 20120330//EN"
[1]=>
string(66) "http://jats.nlm.nih.gov/publishing/1.0/JATS-journalpublishing1.dtd"
[2]=>
array(4) {
["directory"]=>
string(1) "/"
["intSubName"]=>
string(7) "article"
["extSubURI"]=>
string(66) "http://jats.nlm.nih.gov/publishing/1.0/JATS-journalpublishing1.dtd"
["extSubSystem"]=>
string(66) "-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.0 20120330//EN"
}
}
Warning: DOMDocument::loadXML(): Failed to load external entity "-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.0 20120330//EN" in Entity, line: 2 in /in/jemmH on line 18
----
Warning: DOMDocument::loadXML(): php_network_getaddresses: getaddrinfo failed: Name or service not known in /in/jemmH on line 25
Warning: DOMDocument::loadXML(http://jats.nlm.nih.gov/publishing/1.0/JATS-journalpublishing1.dtd): failed to open stream: php_network_getaddresses: getaddrinfo failed: Name or service not known in /in/jemmH on line 25
Notice: DOMDocument::loadXML(): failed to load external entity "http://jats.nlm.nih.gov/publishing/1.0/JATS-journalpublishing1.dtd" in Entity, line: 2 in /in/jemmH on line 25
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)