前言

在一次应用安全测试中发现了一个的Java反序列化漏洞,该漏洞最终导致未经身份验证的远程代码执行。经过实践,发现利用此漏洞并不像之前使用Ysoserial生成默认payload那样简单。

所以在本篇文章中,我将逐步介绍并修改Ysoserial的使用过程以及在其中所遇到的问题。


漏洞利用点

问题一:直接的Payload无法利用

发现点是位于一个解码base64参数的地方,该参数返回了一个像blob类型的二进制数据。

在尝试使用了各种编码和解压缩算法的解码之后,最后发现它是一个用Zlibdeflate算法压缩后的JAVA序列化对象。

Zlib deflate压缩算法:https://blog.csdn.net/u010037928/article/details/90717474

当数据发送到后端后,负责反序列化对象的函数将首先解压缩对象,再进行反序列化。如果看到一个base64编码后的参数,解码后会返回一个blob类型的数据,那就多尝试一些常见通用的编码及解压缩算法,看会不会得到一些有用的数据。

BurpSuite有一款插件叫做Hackvertor,内置很多编码和压缩算法。

Hackvertor对参数进行base64解码,然后使用deflate_decompress将其解压缩,这时会得到一个序列化后的Java对象。

接下来尝试在发送请求之前去使用解压缩后Ysoserial的Payload,但是实践了发现毫无作用,因为就算当Payload在服务器端成功的反序列化之后,如果利用不成功,也不能执行操作。

问题二:类版本不匹配

第二个问题是由于Ysoserial序列化的类版本与服务器端的类版本不匹配生成,引起java.io.InvalidClassException触发。

因为在对象在序列化期间使用的本地类与服务器端类版本不匹配,导致漏洞利用失败。


利用过程

一、采用正确的方法去压缩对象

由于在压缩Payload时无法使用Hackvertor,所以我们可以在生成Payload之前直接在Ysoserial中压缩对象,这是通过修改Ysoserial代码并构建新的Java存档(JAR)来完成的,这样就可以生成有效的Payload,就会在服务器端正确的执行反序列化操作。
将目标对象添加到Ysoserial的GeneratePayload类中压缩,返回它的base64编码后的字符串,最后将base64编码后的对象打印到控制台。

添加到Ysoserial的代码部分,以便在生成有效负载之前对对象应用压缩。

二、解决SerialVersionUID不匹配

现在可以生成正常压缩后的Payload,但依然报错,并且好像没有达到漏洞利用效果。

不过不慌,在状态值为500返回的服务端错误信息里面暴露出足够的信息来解决这个问题。

在这里,可以看到服务器端希望使用的版本为UID-3490850999041592962;

但我们发送的版本为UID-2044202215314119608。

啥是SerialVersionUID?

SerialVersionUID是一个标识符,用于标识类的版本,以确保在序列化过程中使用的类的版本与在服务器端反序列化过程中使用的本地类的版本相同。如果在反序列化时UID值不匹配,会收到一个错误。如果SerialVersionUID没有在代码中显式定义,则通常是在运行时使用computeDefaultSUID方法序列化类时生成的。解决SerialVersionUID不匹配的方法

1、更改在Ysoserial中直接使用的依赖项版本。2、在运行时对来自computeDefaultSUID方法的SUID返回值设置断点,并将其修改为所需的值。3、修改类的字节码以硬编码SerialVersionUID。

简单介绍下后两种方法。

如何在运行时去修改computeDefaultSUID值呢?最简单的附加方法,就是使用适当的类版本去构建Ysoserial。

三、使用匹配的版本构建Yososerial这是生成有相匹配SerialVersionUID的Payload的最NB的方法。
参考前面的返回错误消息,我们需要确定使用哪个版本的commons-beanutils来构建Ysoserial,以便在序列化时使org.apache.commons.beanutils.BeanComparator类获得合适的SerialVersionUID。

一个Bash脚本搞定!去遍历下特定依赖项的所有版本,然后下载每个版本并打印目标类的SerialVersionUID,可以更快的找到我们所需要的版本。

#!/bin/bash#Example usage: ./getSUIDs.sh https://archive.apache.org/dist/commons/beanutils/binaries/ org.apache.commons.beanutils.BeanComparator#Example2 usage: ./getSUIDs.sh https://archive.apache.org/dist/commons/collections/binaries/ org.apache.commons.collections4.functors.InvokerTransformerurl=$1class=$2mkdir tmpjarsfor zip in $(curl -s $url | grep '.zip  wget -O tmpjars/current.zip -4 $url$zip &>/dev/null  unzip tmpjars/current.zip -d tmpjars &>/dev/null  echo "Checking file: $zip"  for jar in $(find tmpjars/ -name '*.jar');do     serialver -classpath $jar $class 2>/dev/null| grep serialVersionUID    done  rm -rf tmpjars/*donerm -d tmpjars/

从前面的错误消息中,我们知道需要查找的是SUID -3490850999041592962。
所以使用脚本:

./getSUIDs.sh https://archive.apache.org/dist/commons/beanutils/binaries/ org.apache.commons.beanutils.BeanComparator

可以看到,在1.7.0版本中有了我们需要的SerialVersionUID。

获取Ysoserial的源代码:

Git clone https://github.com/frohoff/ysoserial.git

在Ysoserial目录中打开pom.xml并修改它,用适当的版本替换commons-beanutils版本(或任何有问题的依赖项)

将1.9.2版本更换为1.7.0

保存并构建Ysoserial:

mvn clean package -DskipTestscd targetjava -jar ysoserial-0.0.6-SNAPSHOT-all.jar

使用Ysoserial使用正确匹配的SerialVersionUID来生成Payload

四、在运行时去修改SerialVersionUID如果在运行时去修改Ysoserial中的SerialVersionUID,就需要选择一个Java调试/编辑器并在computeDefaultSUID的返回值处设置断点。
然后此方法每次返回时就会暂停当前应用程序的运行状态,允许我们根据需要去查找和修改值。
不过这个方法稍微复杂一些,但在某些情况下可能是必要的。

操作步骤:
1、选择获取IntelliJ IDEA的副本,在这里下载Ysoserial。
2、打开IDEA并使用默认值创建一个新的空项目。
3、在左边的文件窗口中将Ysoserial JAR拖到项目上(本此实操位于OpenJDK 11的Kali

Linux上执行)。

4、设置好配置然后在调试器中运行Ysoserial。ALT+SHIFT+F10打开运行菜单,选择“编辑”。

5、将命令参数设置为所需的Ysoserial,在此示例中,我们使用:

CommonsBeanutils1 “nslookup example.com”

在“日志”选项上,可以设置一下输出文件让,更便于使用。

6、为SUID返回值设置断点
返回值来自于java.io中computeDefaultSUID方法的ObjectStreamClass类。
在文件窗口展开如下内容:

External Libraries   Java.base    Java     Io        ObjectStreamClass

7、双击该类并直接搜索return this.suid,然后在102行设置一个断点

可通过单击行号右侧的getSerialVersionUID返回值来查看设置的断点。

8、运行并调试

现在,按ALT+SHIFT+F9在调试器中运行JAR,直到断点处停止。
一步步单步调试跟进,直到需要修改的类serialVersionUID,它是从我们之前收到的错误消息中获得的,本此操作中是BeanComparator。
只需右键单击suid参数,并Set Value将值设置为-3490850999041592962L。

在调试器中修改SerialVersionUID

继续执行,直到Payload输出后,里面应该包含适合这个类的SerialVersionUID。


GetShell:

现在去使用上面所写的任何一种方法,都可以使用正确的SerialVersionUID生成一个压缩的Payload,从而获得一个shell。


结论此类的漏洞通常在探索过程中并不明显,但是我们在进行一些业务应用程序的测试的时候一定要注意任何Base64编码的值。

java restfulapi 返回文件base64_Java反序列化:一次构造后Ysoserial Payload相关推荐

  1. java接口返回pdf时修改文件名称问题

    最近遇到一个问题,java接口返回一个pdf文件,浏览器直接预览,但是预览时显示的文件名称不是在响应头中设置的filename值. 一.问题 未改动代码 测试Controller: @RequestM ...

  2. java实现读取文件返回字节数组

    java实现读取文件的内容返回字节数组 1.代码如下所示: public class FileUtil {/*** 方法功能:读取文件内容返回字节流 * @param String fname* @r ...

  3. JAVA 实现返回PDF文件流并进行下载

    JAVA 实现返回PDF文件流并进行下载 首先确保本地存放pdf 保证通过路径可以拿到文件 我这边把pdf放在e盘下的目录 1.前台方法 原生ajax 发送请求返回文件流进行下载 function d ...

  4. java对象序列化存储到文件、从文件中反序列化读取java对象

    1.首先,对即将要操作的java对象的类需要实现序列化接口Serializable,代码如下: import java.io.Serializable; public class User imple ...

  5. java接收流文件并返回数据

    java接收流文件并返回数据 @RequestMapping(value="/updateStatus") public Object updateStatus(HttpServl ...

  6. JAVA下载 PDF 到本地 或 返回文件流

    @Slf4j public class PDFUtils {/**** @param fileUrl 文件路径* @param saveUrl 文件保存路径* @param fileName 文件名称 ...

  7. K:java中的序列化与反序列化

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?以下内容将围绕这些问题进行展开讨论. Java序列化与反序列化 简单来说Java序列化是指把Java对象转 ...

  8. Java序列化的作用和反序列化

    1.序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来.虽然你可以用你自己的各种各样的方法来保存object states,但 ...

  9. java读取gxk文件,Java中常见的IO流及其使用

    Java中IO流分成两大类,一种是输入流,所有的输入流都直接或间接继承自InputStream抽象类,输入流作为数据的来源,我们可以通过输入流的read方法读取字节数据:另一种是输出流,所有的输出流都 ...

最新文章

  1. Oracle 11 密码永不过期
  2. 【Python】如何在Windows操作系统下安装Python和Networkx
  3. leetcode537. 复数乘法
  4. Python中的yield详解
  5. 10 QM配置-检验计划配置-维护检验批来源并分配检验类型
  6. zynq processing system 参数设置_【正点原子FPGA连载】第六章自定义IP核-呼吸灯实验-领航者 ZYNQ 之嵌入式开发指南...
  7. smb协议讲解_SMB协议详解 - 人之为学,如饮河海,大饮则大盈,小饮则小盈 - OSCHINA - 中文开源技术交流社区...
  8. latex参考文献bib基本格式_Latex如何添加参考文献——使用bib
  9. Solidity入门-开发众筹智能合约
  10. EasyAR4.0使用说明(Unity3D)三----平面图像跟踪扩展:视频播放,涂涂乐
  11. 【概率论与数理统计】p1-4 前言、随机试验、样本空间、事件间的关系、事件的运算及运算法则
  12. Win10突然卡死的原因调查(转自yzhang)
  13. Chatgpt聊天机器人系统开发
  14. 细思极恐---十年生死两茫茫,通信人,意欲亡。
  15. java课程线上线下教学平台 ssm638
  16. 一天一篇latex刘海洋代码解析:1.2.5 遭遇数学公式
  17. 前端水平垂直居中的方法
  18. 网站建设与深度学习(PHP调用Python程序)
  19. 程序猿生存指南-24 加班狂魔
  20. 手把手教你用 wxPython 设计一个可以弹琴的计算器

热门文章

  1. libevent mysql_在 libevent 中使用 MariaDB(MySQL)
  2. eselasticsearch入门_ElasticSearch入门 附.Net Core例子
  3. python3网络编程中semaphore用法_python3 进程信号量semaphore
  4. 汇总|计算机摄影学资源,涉及视频、书籍以及国内外著名实验室
  5. oc中在控件上显示图片
  6. 算法设计:双相机高斯建模算法优化
  7. Git命令配置学习笔记
  8. 第三十一课.矩阵胶囊与EM路由
  9. 自定义request_python3下urllib.request库之Handle处理器和自定义Opener
  10. miniconda安装,及channels配置,安装其他软件