PHP如何禁用外部实体加载来防御XXE libxml_disable_entity_loader函数

发布时间 - 2026-02-02 00:00:00    点击率:
libxml_disable_entity_loader在PHP 7.4+已移除且完全失效;正确方式是针对SimpleXML、DOMDocument分别显式配置禁用外部实体,或PHP 8.0+统一使用libxml_set_external_entity_loader(null)。

libxml_disable_entity_loader 在 PHP 7.4+ 已被移除

直接调用 libxml_disable_entity_loader(true) 在 PHP 7.4 及更新版本会触发 Deprecated: libxml_disable_entity_loader(): This function is deprecated 警告,且**完全失效**。它只在 PHP 5.6–7.3 有效,但即便在这些版本中,也仅影响部分 libxml API(如 simplexml_load_string),对 DOMDocument::loadXML() 等默认行为无效——因为后者不自动继承该全局开关。

正确禁用外部实体的三种可靠方式

必须针对具体 XML 解析器显式配置,不能依赖全局函数:

  • SimpleXML 场景:使用 LIBXML_NOENT | LIBXML_DTDLOAD 以外的选项,并确保不传入 LIBXML_NOENT(它会加载外部实体);更安全的是显式禁用 DTD:
    $xml = simplexml_load_string($raw, 'SimpleXMLElement', LIBXML_NONET | LIBXML_NOCDATA);
  • DOMDocument 场景:必须在实例化后、调用 loadXM

    L()
    load() 前设置属性:
    $dom = new DOMDocument();
    $dom->resolveExternals = false;
    $dom->substituteEntities = false;
    $dom->setEntityLoader(function () { return false; }); // PHP 8.0+
    $dom->loadXML($raw);
  • PHP 8.0+ 统一方案:使用 libxml_set_external_entity_loader(null) 替代已废弃函数,它作用于当前请求上下文,对所有后续 libxml 调用生效(包括 SimpleXML 和 DOM):
    libxml_set_external_entity_loader(null);
    $xml = simplexml_load_string($raw); // 安全
    $dom = new DOMDocument();
    $dom->loadXML($raw); // 安全

为什么只设 LIBXML_NONET 不够

LIBXML_NONET 阻止网络请求,但无法阻止本地 DTD 文件或内联实体定义(如 &xxe; 指向 file:///etc/passwd)。真实 XXE 利用常通过如下方式绕过:

 ]>
&xxe;]]>
此时若未禁用 DTD 解析或实体替换,仍会泄露文件内容。必须组合使用:resolveExternals = false + substituteEntities = false + libxml_set_external_entity_loader(null)

遗留系统兼容 PHP 7.2–7.3 的折中写法

若无法升级 PHP 版本,需同时处理全局开关和实例配置,避免遗漏:

if (function_exists('libxml_disable_entity_loader')) {
    libxml_disable_entity_loader(true);
}
$dom = new DOMDocument();
$dom->resolveExternals = false;
$dom->substituteEntities = false;
$dom->loadXML($raw);
注意:此写法在 PHP 8.0+ 会报弃用警告,上线前务必确认 PHP 版本并清理该调用。

实际防御 XXE 的关键不在“关一个开关”,而在于每个 XML 解析入口都显式关闭实体加载能力——尤其是当代码路径涉及多个解析器(如先用 SimpleXML 再转 DOM),容易漏掉某一处。


# php  # 为什么  # NULL  # xml  # Libxml  # simpleXML  # 继承  # function  # dom  # this  # 会报  # 移除  # 的是  # 加载  # 尤其是  # 多个  # 已被  # 三种  # 只在  # 在这些 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251811 】 【 AI营销90571


相关推荐: Laravel如何使用Blade组件和插槽?(Component代码示例)  油猴 教程,油猴搜脚本为什么会网页无法显示?  Laravel distinct去重查询_Laravel Eloquent去重方法  如何快速生成ASP一键建站模板并优化安全性?  谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复  如何快速上传自定义模板至建站之星?  Laravel模型事件有哪些_Laravel Model Event生命周期详解  laravel怎么通过契约(Contracts)编程_laravel契约(Contracts)编程方法  Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言  如何在阿里云域名上完成建站全流程?  JavaScript常见的五种数组去重的方式  Laravel如何升级到最新版本?(升级指南和步骤)  网站视频制作书签怎么做,ie浏览器怎么将网站固定在书签工具栏?  在centOS 7安装mysql 5.7的详细教程  详解jQuery中的事件  Python数据仓库与ETL构建实战_Airflow调度流程详解  ai格式如何转html_将AI设计稿转换为HTML页面流程【页面】  Java类加载基本过程详细介绍  HTML5空格在Angular项目里怎么处理_Angular中空格的渲染问题【详解】  为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】  如何在IIS管理器中快速创建并配置网站?  BootStrap整体框架之基础布局组件  用yum安装MySQLdb模块的步骤方法  如何快速搭建个人网站并优化SEO?  Laravel如何与Vue.js集成_Laravel + Vue前后端分离项目搭建指南  zabbix利用python脚本发送报警邮件的方法  高防服务器如何保障网站安全无虞?  Laravel如何实现多语言支持_Laravel本地化与国际化(i18n)配置教程  制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?  Laravel如何实现数据导出到CSV文件_Laravel原生流式输出大数据量CSV【方案】  Internet Explorer官网直接进入 IE浏览器在线体验版网址  Laravel如何配置任务调度?(Cron Job示例)  青岛网站建设如何选择本地服务器?  Win11怎样安装网易有道词典_Win11安装词典教程【步骤】  详解Huffman编码算法之Java实现  如何在新浪SAE免费搭建个人博客?  Laravel广播系统如何实现实时通信_Laravel Reverb与WebSockets实战教程  教你用AI润色文章,让你的文字表达更专业  Laravel如何正确地在控制器和模型之间分配逻辑_Laravel代码职责分离与架构建议  网站制作企业,网站的banner和导航栏是指什么?  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?  Laravel怎么进行浏览器测试_Laravel Dusk自动化浏览器测试入门  如何正确下载安装西数主机建站助手?  Laravel的.env文件有什么用_Laravel环境变量配置与管理详解  Laravel如何记录日志_Laravel Logging系统配置与自定义日志通道  如何在自有机房高效搭建专业网站?  Win11怎么关闭专注助手 Win11关闭免打扰模式设置【操作】  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  如何登录建站主机?访问步骤全解析