反序列化漏洞攻击原理(Dubbo反序列化漏洞剖析)

2023-10-27

关联文章:给服务端发送自定义类实例序列化数据实现反序列化攻击

一、前言

最近大家都在讨论Dubbo反序列化漏洞问题。想必各个大V也都推送了相关文章。看了下各大文章差不多都是一个套路,两个步骤:第一步开始描述下Dubbo的反序列化漏洞(几乎都是官方文档内容),第二步说下怎么解决(升级版本即可)。那么我想很多同学并不知道Dubbo反序列化漏洞到底是怎么回事;也不知道,黑客如何利用漏洞进行攻击么。

如果你对上诉问题感兴趣,那么本文将问你一步一步解决反序列化漏洞到底是怎么回事,以及黑客通常会怎样利用反序列化漏洞进行攻击。

如果你是大牛,那么打扰了,哈哈哈哈。

二、序列化与反序列化简介

在进入正文之前我们简单介绍下序列化。在java里面,如果一个类需要序列化,咱们一般都需要实现一个接口Serializable,接着就是序列化与反序列化。

序列化与反序列化一般有两种方式,一种是使用开源组件如hessian等。另外就是自己实现序列化,即将对象实例在输入输出流之间转换。

自己实现比较简单,就是通过输入输出流的readObject和writeObject方法即可。

如果对象比较复杂,在序列化或者反序列化的时候需要做一些处理,则可以让需要序列化与反序列化的类实现readObject和writeObject方法即可。

private void writeObject(java.io.ObjectOutputStream out)
     throws IOException
private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;

三、反序列化怎样才会被利用?

1、说明

反序列化漏洞就是指黑客序列化一个包含恶意代码的实例对象(通常是Runtime.exec来执行后台命令),此时会得到对象的字节数据。然后字节数据通过接口发送到服务端(被攻击的服务器)。服务器在反序列化出对象的过程中(readObject方法里面)就会触发触发恶意代码执行,从而达到攻击的目的。

那么是不是所有对象的反序列化都能够被利用呢?当然不是。比如我们上面说的Person对象。它在反序列化的时候(readObject)中什么也没做。黑客针对Person的反序列化做不到任何入侵。

那么怎样的对象在反序列化的时候才会被利用呢?一般都是重写了readObject方法的对象,其方法的某些逻辑会被利用。下面我们将从一个在JDK7下使用commons-collections-3.1时存在的反序列化漏洞来分析反序列化到底是怎么被利用的。

2、关键类说明-Transformer

在commons-collections中有个接口叫做Transformer,其作用就是将一个对象转换为另外一个对象。多个Transformer可以构成一个Transformer执行链,叫做:ChainedTransformer

在Transformer中有一个牛逼的实现类:InvokerTransformer,就是能够通过反射的方式执行input对象的某个方法,并将结果返回。如下由InvokeTransformer构成的执行链就达到了一个目的,就是在执行transformedChain.transform的时候能够触发Runtime.getRuntime().exec("open .")。即在Mac上打开文件管理器。

3、关键类说明-TransformedMap

TransformedMap是一个由Transformer构造的一个map。可以把任意的map都通过一个Transformer装饰成TransformedMap。装饰之后的TransformedMap的作用是:在执行map.entry.setValue的时候能够调用Transformer对入参value转换之后,然后将转换之后的结果设置到目标(被装饰)map中。

4、关键类说明-AnnotationInvocationHandler

这是JDK自带的一个类,是一个对注解调用的InvocationHandler(proxy的执行类)。这里我们并不关注其作用,而是关心其内部有个memberValues成员是一个map结构(如下)。在反序列化对象AnnotationInvocationHandler的时候,其会执行memberValues中所有的entry.setValue方法。

5、攻击原理

相信看完上面的几个类大家已经晕了,也没有看出来这些类和攻击有什么关系。接下来我们把他们的功能串起来。

A、首先ChainedTransformer链(一个Transformer)可以构造出一个可以调用Runtime.getRuntime.exec方法的链(这个执行链就是执行恶意代码的地方)。但是想要执行它,需要调用其transform方法。

B、接着TransformedMap可以使用一个Transformer(当然可以是一个ChainedTransformer)对普通map进行装饰。装饰后的TransformedMap只要执行其中的entry.setValue就能够触发其中的Transformer.transform方法执行。

C、AnnotationInvocationHandler类有个map成员,在反序列化该类的时候会触发其map的entry.setValue方法被调用。

汇总一下,大家是不是有些明白了,这是一环扣一环(从C到A倒过来看)。我们只要构建一个如下图一样的实例关系就可以实现攻击了。

第一步:通过ChainedTransformer构建一个包括恶意指令的Transformer链;第二步:将ChainedTransformer和普通Map构建成一个装饰类:TransformedMap

第三步:将TransformedMap设置为AnnotationInvocationHandler的MemberValues成员变量。

经过上面三步得到的AnnotationInvocationHandler类被序列化之后得到的二进制数据就具有攻击功能了。接下来我们看下其实在反序列化的时候是如果实现攻击的。

服务端在拿到这些二进制数据之后如果直接反序列化,就会触发如下执行流程:

  1. 首先触发AnnotationInvocationHandler反序列化执行器readObject,会触发其成员memberValues的entry.setValue执行,即执行TransformedMap中的entry.setValue

  2. 然后TransformedMap中的entry.setValue会触发其中的Transformer执行,即会触发ChainedTransformer这个执行链执行

  3. 最终就导致了恶意指令被执行,本例中会打开mac下的文件管理器。

给大家留一个思考题:为什么我们要这样大费周章执行恶意代码呢?为什么我们不自己在本地定义一个实例,让其在readObject的时候直接执行恶意代码。然后将这个实例序列化之后发送到服务端反序列化即可?

6、攻击代码简介

在构造AnnotationInvocationHandler对象的时候通过反射实现,是因为其构造方法不是public的。

四、Dubbo反序列化漏洞剖析

1、Dubbo的漏洞简介

反过来再看Dubbo的反序列化漏洞就很简单了。其实就是其在Http协议的场景时,对发送过来的字节码直接反序列化(未做任何检测)。如果我们通过上述方法就很容易实现攻击了。

下图是Dubbo在Http协议下直接反序列化客户端传递过来的对象的代码实现。

调用链大概是:

Http协议发送数据

  -> HttpProtocol.handle 

  -> HttpInvokerServiceExporter.handleRequest 

  -> HttpInvokerServiceExporter.readRemoteInvocation

  -> RemoteInvocationSerializingExporter.doReadRemoteInvocation

2、漏洞复现步骤

网上有大牛已经做过了,我就不卖弄了,大家直接参考即可:https://www.cnblogs.com/wh4am1/p/12307848.html

3、如何解决漏洞

其实如果要自己解决,可以对输入流进行校验。

而Dubbo最新版本不是直接反序列化了,而是通过google提供的jsonrpc4j组件来反序列化数据。

五、更多的反序列化漏洞

大家可以参考开源的https://github.com/frohoff/ysoserial,上面列举了很多反序列化漏洞的攻击实例,有兴趣可以看看。上面复现Dubbo反序列化漏洞的大牛也是用的这个开源工具实现。

六、惯例

如果你对本文有任何疑问或者高见,欢迎添加公众号共同交流探讨(添加公众号可以获得”Java高级架构“上10G的视频和图文资料哦)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

反序列化漏洞攻击原理(Dubbo反序列化漏洞剖析) 的相关文章

随机推荐

  • idea快速清理无效类文件

    1 右击选中的项目 如下图所示 2 在弹出框中输入 unused declaration点击选择 如下图所示 3 弹出如下图所示 点击ok 此时需要一段时间 4 结果如下图所示 5 此时 一个个选中 然后双击 有4种处理模式 如下图所示 S
  • 基于Distflow的最优潮流模型(OPF)--模型推导篇

    开篇 前言 自打上期内容火电机组经济调度建模及求解 基础篇推出以后 有小伙伴留言 不考虑潮流问题的经济调度都是耍流氓 作为一个有文化的流氓 我们尝试着为大家科普潮流计算 对于电力系统而言 潮流计算是一个非常复杂且重要内容 如果我们推文中有什
  • 俞敏洪:与其有钱,不如值钱

    很多人一辈子有两个追求 一个是有钱 一个是值钱 有的人运气好 出生在富贵之家 一出生就像贾宝玉一样嘴里含着玉 有钱就不是问题 但有钱解决不了第二个问题 也就是你本人值不值钱的问题 值钱是个人价值的体现 比如你去找一份工作 人家给你开出百万年
  • 链表 List.h

    链表 List h include list h include
  • Android指纹门锁ESP32项目

    本教程中我向您展示如何使用指纹扫描仪Android手机通过ESP32或ESP8266 Wifi或Arduino wifi模块进行门解锁 要创建此项目 您需要ESP32 中继模块 电磁门锁和Android手机 所需零件 源代码 详情参阅 亚图
  • layUI 使用select选择框无法显示出样式,看不到、等解决方案

    我们在写layui代码时候可能遇到这样的问题 明明代码都是从layui官网上复制下来的 却还是会看不到相应的元素 就比如我昨天遇到的一个BUG 代码如上 但是页面上却没有显示出选择框 选择框这里却依然没有结果出现 这个问题困扰了我几个小时
  • js下载base64格式的图片

    步骤 1 创建一个a标签 2 给a标签创建点击事件 3 将base64数据转为Blob类型 4 将a标签的href指向Blob类型数据 5 触发a标签 代码 template vue qr 组件可以自动将 text绑定的url地址转换为二维
  • 【Python零基础入门篇 · 9】:字典的相关操作

    文章目录 字典 键 值 字典的基本格式 字典的定义 键值对 键的唯一性 字典的常见操作一 增删改查 查看元素 根据键名返回值 删除元素 del clear 修改元素 添加元素 字典中的常见操作二 len 求长度 dict keys dict
  • SQL语句:查询数据表的前n行信息

    每种数据库使用的关键字都不一样 每种数据库使用的关键字都不一样 每种数据库使用的关键字都不一样 SQL Server MS Access 语法 TOP SELECT TOP number percent column name s FROM
  • Java 模拟百度翻译

    相信百度翻译对于大家来说并不陌生 本案例要求编写一个程序模拟百度翻译 用户输入英文之后搜索程序中对应的中文 如果搜索到对应的中文就输出搜索结果 反之给出提示 package demo52 import java util HashMap i
  • sv面向对象:类

    写在前面 开始修炼 类是通过代码怎么体现 实例1 定义一个类 systemverilog绿皮书 例5 1简单的 Transaction类 class Transaction bit 31 0 addr crc data 8 class pr
  • Tomcat配置SSL证书

    本地配置ssl证书 为了更好的再服务器上配置ssl证书 先在本上上熟悉流程 本地不需要类似阿里云的证书 借助java的keytool帮助生成离线的证书 keytool genkey alias ceshi storetype PKCS12
  • MVC和MVVM【区别和详解】

    本篇文章的主要内容是给大家讲解一下MVC与MVVM思想之间的区别 希望能对你有所帮助 他们的区别主要在于MVC中Controller 控制层 变成了MVVM中的viewModel 双向数据绑定 MVVM解决了MVC中需要大量操作DOM所带来
  • std : : vector

    一 简介 std vector 的底层实现通常基于动态数组 dynamic array 它是一种连续分配的内存块 允许元素的快速随机访问 下面是 std vector 的一些关键特点和底层实现细节 连续内存块 std vector 内部使用
  • 【从零学习openCV】ubuntu+openCV+qt安装配置

    一 Ubuntu安装 ubuntu是linux的一个发行版本 我想对linux有所了解的人应该都知道 我们直接到官网上下载就好了 是免费使用的 官网下载链接 这里我用的是最新的ubuntu14 04 由于我用的是Mac系统 直接用Vmwar
  • Windows中一些宏的含义

    1 WIN32 WINDOWS WIN32 WINNT WINVER 这三个宏其实都是Windows的版本宏 在Windows 95 98 Me这一分支的OS中 Windows的定义的版本宏是 WIN32 WINDOWS 与此同时 Wind
  • net : 无法将“net”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然 后

    可能是系统的环境变量没有配置好 所以需要在 C Windows System32下才能找到该命令 是执行该命令的意思 net start mysql 无法启动mysql 根据提示解决了问题 改成 net stop mysql80 net s
  • 多个promise并发执行,如果某个promise失败,则尝试重新执行该promise一次,如果还是失败则提示错误

    思路 可以使用 Promise all 和Promise catch 结合的方式来实现多个promise的并发执行 并在某个promise失败时尝试重新执行 首先 将所有的promise放入数组中 并使用Promise all 来同时执行这
  • json-server深入探秘

    JSON Server Get a full fake REST API with zero coding in less than 30 seconds seriously Created with lt 3 for front end
  • 反序列化漏洞攻击原理(Dubbo反序列化漏洞剖析)

    关联文章 给服务端发送自定义类实例序列化数据实现反序列化攻击 一 前言 最近大家都在讨论Dubbo反序列化漏洞问题 想必各个大V也都推送了相关文章 看了下各大文章差不多都是一个套路 两个步骤 第一步开始描述下Dubbo的反序列化漏洞 几乎都