对于XXE漏洞的理解以及在实战中的利用

您所在的位置:网站首页 漏洞分析是什么 对于XXE漏洞的理解以及在实战中的利用

对于XXE漏洞的理解以及在实战中的利用

#对于XXE漏洞的理解以及在实战中的利用| 来源: 网络整理| 查看: 265

1.概念

XXE(XML External Entity Injection) 全称为 XML 外部实体注入

2.语法XML 指可扩展标记语言(EXtensible Markup Language)XML 是一种标记语言,很类似 HTMLXML 被设计为传输和存储数据,其焦点是数据的内容XML 被设计用来结构化、存储以及传输信息XML 允许创作者定义自己的标签和自己的文档结构3.结构1.XML 文档声明,在文档的第一行2.XML 文档类型定义,即DTD,XXE 漏洞所在的地方3.XML 文档元素4.介绍一下XML文档​

Hello World​

               001                zhangsanBeijing50

               002                lisi北京​

注:

文档注释用包围,不允许嵌套,允许多行注释。

XML里面的元素严格区分大小写。

XML文档必须有且只有一个根元素。(根元素是一个完全包括文档中其他所有元素的元素。)

0x01:XML文档说明

每一个XML文档都以一个XML声明开始,用以指明所用的XML的版本。

XML声明有version 、encoding和standalone特性。

version特性表明这个文档符合XML 1.0规范。

encoding 属性指定了编码格式,默认情况下是utf-8,这个属性要放在属性前面。

像standalone是XML文档的属性,位于等号左边的是特姓名,而其值位于等号的右边,并用双引号或单引号括起来。

自定义的元素也可以有一个或多个属性,其属性值使用单引号或者双引号括起来。

如果属性值中有双引号则使用单引号,反之亦然。

属性的形式为:

属性名= "属性值",比如gender="male"。

多个属性值之间用空格隔开(一个或多个空格都可以)。

在一个元素上,相同的属性只能出现一次。

属性值不能包含, &。

0x02:实体

实体叫ENTITY,实体的作用是避免重复输入。

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

1679019845_6413cf450624a6d44afa6.png!small?1679019845632

自定义实体语法:

​]>​引用已定义的实体:​&实体名;0x03:处理指令PI

处理指令用于XML解析器传递信息到应用程序。

语法:

PI必须以一个叫做目标的标识符开头,这个标识符遵从如同元素和属性一样的规则,目标是指令所指向的应用的名称,指令是传递给应用程序的信息。

0x04:CDATA节

用于把整段文本解释为纯字符数据而不是标记的情况。

包含大量的、&、或者"字符。CDATA节中的所有字符都会被当做元素字符数据的常量部分,而不是XML标记。

语法:

​......​]]>

可以输入任意字符(除]]外),不能嵌套。

​​

这里放任何内容都是合法的

]]> ​

0x05:PCDATA节

PCDATA表示已解析的字符数据。

PCDATA的意思是被解析的字符数据(parsed character data)。可以把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。PCDATA是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。文本中的标签会被当作标记来处理,而实体会被展开。但是,被解析的字符数据不应当包含任何& < >字符;需要使用& < >实体来分别替换它们。

5.什么是DTD

DTD是XML文档的一个格式规范

exp:

//这一行是 XML 文档定义#这里就是为根元素message定义了4个子元素,receiver,sender,header,msg,然后这4个元素必须要出现而且要按照顺序6.DTD的三种应用形式:1.内部DTD文档exp:]>2.外部DTD文档exp:外部的DTD文档1233.内外部DTD文档结合exp:]>7.DTD元素

1679019860_6413cf54278144a8f9a47.png!small?1679019860962

8.DTD实体内部实体

一个实体由三部分构成:&符号, 一个实体名称, 以及一个分号(;)

exp:]>xxe;这里定义的实体是xxe,实体的值是hello外部实体

XML中对数据的引用称为实体,实体中有一类叫外部实体,用来引入外部资源,有SYSTEM和PUBLIC两个关键字,表示实体来自本地计算机还是公共计算机,外部实体的引用可以利用如下协议

file:///path/to/file.exthttp://url/file.extphp://filter/read=convert.base64-encode/resource=conf.php

1679019887_6413cf6fb8ecdaddd978b.png!small?1679019888639

参数实体exp:%xxe;]>evil;外部evil.dtd的内容公共实体9.利用XXE攻击

1679019902_6413cf7e078a28c935605.png!small?1679019903048

读取任意文件有回显

我们结合具体题目来分析。

例题:

1.picoctf2023 SOAP

题目提示我们要看系统配置文件/etc/passwd

有三个按钮,都点了一下没有东西

看一下源码,源码有一个xml的js文件看一下

1679019916_6413cf8c875f5fd014dcf.png!small?1679019917075

window.contentType = 'application/xml'; function payload(data) { var xml = ''; xml += ''; for(var pair of data.entries()) { var key = pair[0]; var value = pair[1]; xml += '' + value + ''; } xml += ''; return xml; }

这里有一个XML文档说明

以及说明了XML的根元素为data

抓一下包看一下

1679019957_6413cfb5bf066fac1570b.png!small?1679019958302

这里POST了一个ID的变量,我这里猜测ID就是key(题目的DTD感觉缺失了一些东西)

构造我们的payload

2xxe;

发现无回显,继续检查一下,发现我们这里的Content-Type为application/x-www-form-urlencoded,这就是问题所在

参考Content-Type 详解_contenttype_leoss.H的博客-CSDN博客

改为application/xml,发现成功得到flag

1679019972_6413cfc439bf036eec006.png!small?1679019972971

2.[NCTF 2019]Fake XML cookbook

随便测试一下,发现通过报错信息回显

1679019981_6413cfcd26bb11d9b2e76.png!small?1679019981801

查看一下源码

function doLogin(){var username = $("#username").val();var password = $("#password").val();if(username == "" || password == ""){alert("Please enter the username and password!");return;}

var data = "" + username + "" + password + ""; $.ajax({type: "POST",url: "doLogin.php",contentType: "application/xml;",data: data,dataType: "xml",anysc: false,success: function (result) {var code = result.getElementsByTagName("code")[0].childNodes[0].nodeValue;var msg = result.getElementsByTagName("msg")[0].childNodes[0].nodeValue;if(code == "0"){$(".msg").text(msg + " login fail!");}else if(code == "1"){$(".msg").text(msg + " login success!");}else{$(".msg").text("error:" + msg);}},error: function (XMLHttpRequest,textStatus,errorThrown) {$(".msg").text(errorThrown + ':' + textStatus);}

这里给出了我们DTD,我们根据DTD进行构造payload即可

]>2xxe;11

成功回显

1679019992_6413cfd86708b3d81ef49.png!small?1679019993041

尝试直接读取flag

]>2xxe;113.[NCTF 2019]True XML cookbook

跟上一道题的源码一样,尝试沿用上题的payload发现不能直接获取flag了,尝试利用XXE进行RCE,发现应该是php没有装有expect扩展,无法实现RCE

就感觉有可能是内网探测

利用/proc/net/arp读取到内网的另一台服务器的IP地址172.18.0.1

尝试爆破端口,我爆破到10000多也没有什么信息,

之后查看内网存活主机/etc/hosts

1679020000_6413cfe0ba35a2c98a4b6.png!small?1679020001349

发现有一台存活主机

直接访问发现不行,就利用BP爆破跑内网存活主机,跑出flag

1679020008_6413cfe8268ae7ccac8a1.png!small?1679020008824

无回显

也就是我们的blind xxe,一般没有echo,return这些函数,返回不了数值

(需要在自己的VPS上配置上http服务,可以从公网访问我们的dtd文件和xml文件)

方案一:

在自己的VPS上创建一个test.php

再创建一个index.php

%remote;%all;%send; ]> EOF; $data = simplexml_load_string($xml) ; echo "" ; print_r($data) ; ?>

再创建一个test.xml

当访问http://vps-ip/index.php, 存在漏洞的服务器会读出text.txt内容,发送给攻击者服务器上的test.php,然后把读取的数据保存到本地的test.txt中。

方案二

可以将文件内容发送到远程服务器,然后读取。

exp: %dtd; %all; ]> send;

然后在自己的VPS上创建一个evil.xml,内容为

用来获取用户的配置文件

方案三

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

exp:%dtd;%send;]>

evil.dtd的内容,内部的%号要进行实体编码成%。下面是具体的代码实现

“”>%all;

如果有报错的话直接查看VPS的报错信息能得到aaa.php的base64编码后的结果

没有的话可以查看VPS的日志信息,能看到经过base64编码后的数据

方案四

其实跟方案四差不多,但是可以利用监听VPS端口来获取信息

方法是在自己的VPS上创建一个evil.dtd

exp:%dtd;%xxe;

之后再根据题目的要求,上传一个payload

exp:%aaa;]>66666

之后在自己的VPS上监听3333端口就行

python -m http.server 3333#前提是自己的VPS需要配置好http服务命令执行

在php环境下,xml命令执行需要php装有expect扩展,但该扩展默认没有安装,所以一般来说命令执行是比较难利用,但不排除有幸运的情况咯,这里就搬一下大师傅的代码以供参考:

]>f;EOF;$data = simplexml_load_string($xml);print_r($data);?>探测端口

适用于有回显和blind xxe,是外部一般实体

exp:​​content;

根据响应时间判断:(看BP右下角的响应时间)

开放端口,响应时间为16millis

未开放端口,延迟反应1047millis

DOS攻击

参考十亿笑攻击 - 维基百科 (wikipedia.org)

]>lol9;

XML解析器尝试解析该文件时,由于DTD的定义指数级展开(即递归引用),举个例子,这里定义了一个lol的实体,实体还有“lol”的字符串,然后定义了一个lol2的实体,里面有10个"lol"的字符串,依次递推,一个lol3实体引用10个lol2实体,这样的话可以一直向服务器传输文件,也就是形成了DOS攻击,经过XML解析器解析后的内存占用会比其本身大的多。

参考

XML外部实体注入 - 先知社区 (aliyun.com)

一篇文章带你深入理解漏洞之 XXE 漏洞 - 先知社区 (aliyun.com)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3