Java安全学习01-反序列化-入门
2022-8-6 16:49:43 Author: NOVASEC(查看原文) 阅读量:32 收藏

Java安全学习01-反序列化-入门

△△△点击上方“蓝字”关注我们了解更多精彩
0x00 Preface
原本进入甲方,都想划水过日子了,然后发现和开发沟通的时候,如果自己的代码能力不跟上来,非常难和开发沟通,而且对方也不太会信服,所以说,进入甲方,可能是不错,但是,别搞应用安全,搞了就要学代码,不然和开发沟通的时候,说错话会被开发当作c2I=
本文本人学习Java安全第一篇笔记,不是学Java的第一篇笔记,其中的内容可能稍微有点前置知识,不过应该是只是一些简单的基础知识。本文目前还不够完善,措辞可能有误,或者个人理解有误,若有大佬发现错误支持,烦请指出,非常感谢
0x01 序列化/反序列化原理
一些当初学习的笔记,属于知识概括,简单来说就是:
  • writeObject()方法序列化
  • readObject()方法反序列化
  • 一个对象要想被序列化,该对象所属的类必须实现Serializable接口
序列化:public class ObjectOutputStreamextends OutputStreamimplements ObjectOutput, ObjectStreamConstantsObjectOutputStreamJava对象的原始数据类型和图形写入OutputStream可以使用ObjectInputStream读取(重构)对象。可以通过使用流的文件来完成对象的持久存储。如果流是网络套接字流,则可以在另一个主机或另一个进程中重新构建对象。
public ObjectOutputStream(OutputStream out) throws IOException创建一个写入指定OutputStreamObjectOutputStream此构造函数将序列化流标头写入基础流; 调用者可能希望立即刷新流以确保接收ObjectInputStreams的构造函数在读取头时不会阻塞。
public final void writeObject(Object obj) throws IOException将指定的对象写入ObjectOutputStream。写入对象的类,类的签名,以及类的非瞬态和非静态字段及其所有超类型的值。可以使用writeObject和readObject方法覆盖类的默认序列化。该对象引用的对象是可传递的,因此可以通过ObjectInputStream重建完整的对象等效图。
注意:一个对象要想被序列化,该对象所属的类必须实现Serializable接口Serializable只是一个标记接口,实现该接口,不需要重写任何方法

反序列化:public class ObjectInputStreamextends InputStreamimplements ObjectInput, ObjectStreamConstantsObjectInputStream对先前使用ObjectOutputStream编写的原始数据和对象进行反序列化。
public ObjectInputStream(InputStream in) throws IOException创建一个从指定的InputStream读取的ObjectInputStream。从流中读取序列化流头并进行验证。此构造函数将阻塞,直到相应的ObjectOutputStream已写入并刷新标头。
public final Object readObject() throws IOException, ClassNotFoundException从ObjectInputStream中读取一个对象。读取对象的类,类的签名,以及类的非瞬态和非静态字段及其所有超类型的值。可以使用writeObject和readObject方法覆盖类的默认反序列化。这个对象引用的对象是可传递的,因此readObject可以重建完整的等效对象图。

0x02 序列化/反序列化demo
根据上面所介绍的,这里是一个小案例
1、一个对象要想被序列化,该对象所属的类必须实现Serializable接口。
一个实体类,用于实例化一个student 对象,可以看到这个实体类实现了Serializable接口,这里用了lombok,该工具简化了实体类的编写,比如不用写get/set/toString方法等
package com.lwwsechh.vullearn.entity;
import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data@AllArgsConstructor@NoArgsConstructorpublic class student implements Serializable {
private String sid; private String name; private String address;    private int age;}

2、writeObject()方法序列化

序列化一个对象,其中存放学生数据

package com.lwwsechh.vullearn.utils;
import com.lwwsechh.vullearn.entity.student;
import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;
public class SerializableDemo { public static void main(String[] args) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src/main/resources/studentinfo1.txt"));
student s = new student("1","lww","sz",18);
oos.writeObject(s); oos.close(); }}

3、readObject()方法反序列化

反序列化一个对象文件,取出其中存放的学生数据

package com.lwwsechh.vullearn.utils;
import com.lwwsechh.vullearn.entity.student;
import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;
public class UnSerializableDemo { public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/main/resources/studentinfo1.txt"));
Object obj = ois.readObject(); //向下转型 student s = (student) obj; System.out.println(s.getSid()+","+s.getAddress()+","+s.getName()+","+s.getAge());
ois.close(); }}

反序列化结果:

0x03 思考1
这部分我自己也没想全,也还有很多困惑
好像没什么特殊的地方,为什么反序列化会产生安全问题?
是否可以控制readObject?
首先可以确定的是,反序列化会走到readObject()方法,readObject()方法是官方方法,应该没办法去修改,去源码里面写一些执行代码的语句,那是否有可能在其它位置去实现呢?
0x04 一种最简单的方式
最简单,很多时候也意味着几乎遇不到
在实体类里面重写(也许应该叫自定义)readObject()方法
如下,在实体类里面写了一个readObject(),其中写了一个执行系统命令的语句
package com.lwwsechh.vullearn.entity;
import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;
import java.io.IOException;import java.io.Serializable;
@Data@AllArgsConstructor@NoArgsConstructorpublic class student implements Serializable {
private String sid; private String name; private String address; private int age;

//底层在进行判断的时候,会判断实体类中是否存在序列化或反序列化方法,如果存在,那么就会执行该方法,而不用默认方法 private void readObject(java.io.ObjectInputStream ois) throws IOException, ClassNotFoundException { //执行 JVM 默认的序列化操作,进行默认赋值字段的值 ois.defaultReadObject(); Runtime.getRuntime().exec("calc"); }
}

当将其序列化后,再反序列化时,执行了其中的语句

0x05 思考2
上面的方式实在是过于简单了,也许开发实习生会这么写?那么,是否还有更多的可能性呢?
上面的方式是在实体类里面直接写readObject()方法,这种情况难得一遇。
那么如果实体类里面有个属性,它是接受一个类对象呢?这个类里面有危险方法,然后在反序列化的时候被触发?
上面这是一个想法,如果上面这种也不行,那么能不能这样,实体类里面有可控制的类a,然后类a又调用了其它有危险方法的类b,在反序列化的时候被触发?
0x06 总结
本文是第一篇,预计接下来7天内会更新下一篇,如果有师傅急着看,可以去b站看白日梦组长的视频,可能需要一些基础,并且需要跟着调试学习,不然一个视频三十分钟左右可能会让人犯困。
不过还是要给团队拉一些关注的,去看组长的视频,可能有的很基础的,他不会说,但是我这里应该会说,因为我可能有困惑,就会去查,去理解,然后写在自己的笔记里面。
下一篇会先更新关于反射的内容,反射是一个很重要的知识点,如果能理解,对于后续的各种链的学习,有很大的帮助。

1、本团队任何实战都是已授权的、任何技术及工具也仅用于学习分享,请勿用于任何非法、违法活动,如有违背请自行承担后果,感谢大家的支持!!!

2、本团队一贯秉承Free共享的精神,但是也有大家的小愿望,因此本团队所有分享工具,严禁不经过授权的公开分享,被关注就是对我们付出的精力做的最大的支持。

END

如您有任何投稿、问题、建议、需求、合作、后台留言NOVASEC公众号!

或添加NOVASEC-MOYU 以便于及时回复。

感谢大哥们的对NOVASEC的支持点赞和关注

加入我们与萌新一起成长吧!

本团队任何技术及文件仅用于学习分享,请勿用于任何违法活动,感谢大家的支持!


文章来源: http://mp.weixin.qq.com/s?__biz=MzUzODU3ODA0MA==&mid=2247487744&idx=1&sn=5efe59b7f4cdfca711f0b7e283ba98cc&chksm=fad4cc17cda345018665d1023b672d295e235b0e0627f5b9033e15ce24537dfa2829e2ff4eba#rd
如有侵权请联系:admin#unsafe.sh