1.对象序列化
对象序列化是一个用于将对象的状态转换为字节流的过程,该字节流可以保存到磁盘文件或通过网络发送到任何其他程序。 可以通过实现 java.io. 在 Java 类中启用可串行性。
序列化的简单实现示例如下:
班级 {
姓名;
(姓名){
this.name = 名称;
(){
“我的名字是” + 名字;
使用以下代码将其序列化到文件中:
无效主([]参数){
=新的(“”);
文件 file = new File("E:"+ File.+"text.txt");
oos = 空;
输出=新的(文件);
oos = 新的(出);
oos.();
oos.close();
文件中保存的内容如下:
�í�sr�com..demo.ötB&�óO��L�namet�Ljava/lang/;xpt�
上面保存的内容是二进制数据。 保存的文件本身不能直接修改,因为这会破坏其保存的格式。
2.对象反序列化
使用对象输入流读入对象的过程称为反序列化。 简单来说,就是从一组序列化的二进制流中重构出一个对象的过程。
与反序列化密切相关的是对象输入流及其方法()
以下代码的工作原理是将上面序列化的二进制流读取到文件中。
无效主([]参数){
文件 file = new File("E:"+ File.+"text.txt");
ois = 空;
输入=新(文件);
ois = 新(输入);
= ois.();
ois.close();
。出去。(。());
上述代码的输出如下:
{名称=''}
接下来,如果向反序列化的目标对象添加一个方法,如下:
班级 {
姓名;
(姓名){
this.name = 名称;
@
() {
“{”+
"名称='" + 名称 + '\'' +
'}';
空白 ( )
, 在{
.out.("这是,哈哈");
那么上面的反序列化代码将会输出如下结果:
这是,哈哈
{名称='空'}
从上面可以看出,如果在反序列化的目标对象中重写了一个方法,那么反序列化的结果就是不再读取文件中的二进制流,而是直接执行重写的方法。 反序列化漏洞就来自这个地方。
如果目标对象执行一些比较复杂的操作,就很有可能为恶意代码提供可乘之机。 例如,在该方法中实现一个弹出计算器:
空白 ( )
{
=Class.("java.lang.")
.("",新类[]{})
。(无效的);
类.("java.lang.")
.(“执行”,.class)
.(,"calc.exe");
然后执行上面的main方法,就会弹出计算器,如下图:
1.png
3. 反序列化漏洞
反序列化漏洞是指程序传输不安全的反序列化对象,而程序没有对不安全对象进行过滤或限制,导致执行对系统有破坏性的不安全操作。
下面主要分析包中的反序列化漏洞。
4. 反序列化漏洞
此示例使用易受攻击的版本 3.1 进行说明。
4.1. 定义
它到底有什么奇妙的用途,让、、JBoss、、等纷纷对它青睐有加。 为了说明这一点,引用博客中的一段话:
这个包对Java中的集合类做了一些补充,定义了一些全新的集合,当然还实现了接口,比如Bag。 也有原来集合的新版本,eg 最后,更重要的是一系列utils类,为我们提供了常用的集合操作,可以极大方便我们的日常编程。
具体用途我还没有做过深入的研究。 本文主要关注为什么这个包存在反序列化漏洞。 通过一系列排查,发现该包中的反序列化漏洞是由 和 引起的。
4.2. 简要分析
该类用于对Map执行某些转换。 当我们修改Map中的某个值时,无论是key还是value,都会触发我们预定义的某些操作来处理Map。 该对象的实例化是通过其静态方法获得的,如下:
地图 = .(地图, , );
其中,map是一个普通的Map,分别对应key变化和value变化时需要进行的操作,其类型实现了该接口。 接口定义如下:
{
(变量1);
仅定义了一种方法。 当键或值发生变化时,将调用此方法。 如果需要触发一系列操作,可以自己定义。 具体操作如下:
首先定义一个数组:
[] = 新[] {
新的(...),
新的(...),
……
};
第二个实例化:
=新的();
最后传入实例化参数:
地图 = .(地图, 空, );
此时,如果map中的值发生变化,则会调用中定义的方法:
( ) {
for(int i = 0; i < this..; ++i) {
= 这个.[i].();
;
正如你所看到的,该类中的方法会将上一个转换的结果作为下一个转换的输入,直到所有转换完成并返回最终的转换。
现在真正的主角出现了。 如果变换链中有的话,也会调用该方法,其对应的方法实现如下:
(输入) {
如果(输入==空){
无效的;
} 别的 {
尝试 {
类 cls = 输入。();
= cls.(这个.,这个.);
.(输入,this.iArgs);
} catch (n var5) {
throw new (": '" + this.+ "' on '" + input.() + "' 不存在");
} catch(在 var6 上){
throw new (": '" + this.+ "' on '" + input.() + "' be ");
} catch (ption var7) {
throw new (": '" + this.+ "' on '" + input.() + "' 抛出了一个 ", var7);
从这里可以看出,它利用了反射机制来调用相应的方法。 如果输入是可控的,一些非法物体进入,就会带来安全隐患。 那么如何利用这个漏洞呢?
4.3. 利用率
成功使用需要满足的条件如下:
1. 序列化对象不安全
2. 反序列化对象有重写方法
3、外部触发方式
综合上述条件,简单利用该漏洞的序列化对象如下:
com..演示;
蒙斯..;
蒙斯……;
蒙斯……;
蒙斯……;
蒙斯..地图.;
java.io.*;
java.util.;
java.util.Map;
/**
* 反序列化
* @:兴.hang