1

我已将我的 zend 框架版本从 1.11 切换到 1.12.3 在测试中,我检测到一个我无法解释的奇怪错误。我有一些对我大喊大叫的 xml 获取和处理例程。

PHP Fatal error:  Uncaught exception 'Zend_Dom_Exception' with message 
'Invalid XML: Detected use of illegal DOCTYPE' in ....

在 zend 框架 1.11 中,我有 library/Zend/Dom/Query.php:197:

switch ($type) {
    case self::DOC_XML:
        $success = $domDoc->loadXML($document);
        break;
....

在 1.12 中,代码看起来很奇怪

switch ($type) {
   case self::DOC_XML:
       $success = $domDoc->loadXML($document);
       foreach ($domDoc->childNodes as $child) {
           if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
               require_once 'Zend/Dom/Exception.php';
               throw new Zend_Dom_Exception(
                    'Invalid XML: Detected use of illegal DOCTYPE'
               );
            }
       }
       break;
.....

如果我做对了,这个例程将不会用 doctype 解析 doc xml。在我的计算机上一直失败的小例子:

require_once 'Zend/Dom/Query.php'; 
$f = '<?xml version="1.0" standalone="yes"?>' .
    '<!DOCTYPE hallo [<!ELEMENT hallo (#PCDATA)>]>' .
    '<hallo>Hallo Welt!</hallo>';

$dom = new Zend_Dom_Query($f);
$results = $dom->queryXpath('//hallo');

谁可以给我解释一下这个???我测试了 Zend Framework 1.12.3 和 php 5.3.2 和 5.4.6

4

2 回答 2

1

好的,我和 Matthew Weier O'Phinney 聊了聊,以及 DOCTYPES 不再被接受的原因。原因是这里的安全补丁http://framework.zend.com/security/advisory/ZF2012-02

他们禁用了 doctype 功能以防止 XXE 和 XEE。

“我关闭了报告,因为它是我们无法解决的问题,由于安全隐患。它是否是有效的 XML 无关紧要——XEE 和 XXE 向量利用完全有效的 XML 来利用底层 XML 解析器中的问题。因为我们不能控制在每个部署了 ZF 的 PHP 发行版中使用什么版本的 libxml,我们必须在代码中进行防御。此外,当我们添加一个开关以禁用 XEE 和 XXE 矢量检查时,人们会在不了解该开关的情况下使用该开关他们背后的原因。

如果您无法控制 XML 的来源并且仍想使用我们的工具对其进行解析,那么您可以使用许多工具来预处理 XML——包括 pandoc 或 PHP 中的 PCRE 工具。”

我已经提到这已经在 2012 年由 libxml2 本身修复了。但他认为他们不知道在特殊情况下使用了 libxml2 的巫婆版本。

那么解决方案有哪些呢?

  1. 使用 XML 预处理器
  2. 编写一个补丁来删除这些更改(仅当您确定使用 XXE XEE 修补的 libxml2 版本时)
  3. 编写自己的组件
  4. 使用 php 组件 SimpleXMLElement 或 DomDocument

谢谢罗兰多·伊西多罗的帮助:)

于 2013-07-01T11:01:03.590 回答
1

我和你读的一样。谷歌搜索了一段时间,在w3schools 的文章中找到了以下内容:HTML <!DOCTYPE> Declaration

声明必须是 HTML 文档中的第一件事,在标记之前。

我根据您的示例编写了一个小测试,只是将<!DOCTYPE>声明移到了 XML 的顶部,它似乎可以工作:

<?php
require_once 'Zend/Dom/Query.php'; 
$f = <<<XML
<!DOCTYPE hallo [<!ELEMENT hallo (#PCDATA)>]>
<?xml version="1.0" standalone="yes"?>
<hallo>Hallo Welt!</hallo>
XML;

$dom     = new Zend_Dom_Query($f);
$results = $dom->queryXpath('//hallo');

foreach ($results as $result) {
    echo $result->C14N();
}

输出:

<hallo>Hallo Welt!</hallo>
于 2013-06-28T10:54:24.440 回答