XML <!ENTITY e SYSTEM "/path/to/file"> 不适用于 PHP SimpleXMLElement

Posted

技术标签:

【中文标题】XML <!ENTITY e SYSTEM "/path/to/file"> 不适用于 PHP SimpleXMLElement【英文标题】:XML <!ENTITY e SYSTEM "/path/to/file"> does not work with 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 不太可能是合法用途 【参考方案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);

【讨论】:

以上是关于XML <!ENTITY e SYSTEM "/path/to/file"> 不适用于 PHP SimpleXMLElement的主要内容,如果未能解决你的问题,请参考以下文章

MVC开发中的常见错误-03-System.Data.Entity.Validation.DbEntityValidationException: 对一个或多个实体的验证失败。有关详细信息,请参见“E

方法 System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Proyect.Models.Entity>.HasMan

XML External Entity 漏洞

DOMDocument::loadXML(): AttValue: &quot; or ' expected in Entity, line: 报错

EF生成 类型“System.Data.Entity.DbContext”在未被引用的程序集中定义

Hibernate —— Entity.hbm.xml