【问题标题】:XML <!ENTITY e SYSTEM "/path/to/file"> does not work with PHP SimpleXMLElementXML <!ENTITY e SYSTEM "/path/to/file"> 不适用于 PHP SimpleXMLElement
【发布时间】:2022-01-03 18:53:41
【问题描述】:
<?php

$str = <<<XML
<?xml version="1.0"?>
<!DOCTYPE doc [
    <!ENTITY e SYSTEM "/tmp/exp">
]>
<tag>&e;</tag>
XML;

$xml = new SimpleXMLElement($str);

echo $xml;

?>

这应该打印出/tmp/exp 的内容,但没有,我不明白为什么,即使我使用sudo 运行脚本或将/tmp/exp 文件权限更改为777

【问题讨论】:

  • 尝试将LIBXML_NOENT 作为第二个参数传递给构造函数:3v4l.org/nTvDp
  • @ChrisHaas 成功了,谢谢!
  • @ChrisHaas 在推荐打开该选项之前,您应该了解为什么它默认不打开:它已涉及许多安全漏洞,因此需要谨慎使用。
  • @IMSoP,我 100% 同意,但似乎这也可能是 OP 的目的。
  • @ChrisHaas 不一定;显然,我的答案中的示例是一个不切实际的严格过滤器,但关键是您可以拥有一个可以从何处加载实体的白名单 - 例如加载/etc/passwd 不太可能是合法用途

标签: php xml xml-parsing


【解决方案1】:

默认情况下禁用加载外部实体,因为它可能导致various security vulnerabilities

要安全地启用它,您需要register a custom entity loader,它可以检查预期的实体路径并决定是否加载它们。例如,您可能允许特定目录中的任何文件,但不允许磁盘上的其他位置 - 您可能不需要允许引用像 /etc/passwd 这样的系统文件。或者,您可以将提供的路径映射到系统上完全不同的位置。

然后您还需要提供the LIBXML_NOENT option 来告诉解析器通过您的处理程序扩展实体。

例如:

libxml_set_external_entity_loader(function($public, $system, $context) {
    if ($system === '/tmp/exp') {
        return fopen('/tmp/exp', 'r');
    }
    else {
        return null;
    }
});
$xml = new SimpleXMLElement($str, LIBXML_NOENT);

【讨论】:

    猜你喜欢
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-31
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    • 2012-07-23
    相关资源
    最近更新 更多