前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >分析JEP 290机制的Java实现

分析JEP 290机制的Java实现

作者头像
FB客服
发布2022-11-14 16:06:23
5760
发布2022-11-14 16:06:23
举报
文章被收录于专栏:FreeBufFreeBuf

简介

JEP290是Java官方提供的一套来防御反序列化的机制,其核心在于提供了一个ObjectInputFilter接口,通过设置filter对象,然后在反序列化(ObjectInputStream#readObject)的时候触发filter的检测.

JEP 290 在 JDK 9 中加入,但在 JDK 6,7,8 一些高版本中也添加了:

代码语言:javascript
复制

Java? SE Development Kit 8, Update 121 (JDK 8u121)

Java? SE Development Kit 7, Update 131 (JDK 7u131)

Java? SE Development Kit 6, Update 141 (JDK 6u141)


处理

我这里的JDK是 8u202版本。

ObjectInputStream

对于ObjectInputStream类来说,主要的过滤方法为filterCheck

根据注释,我们知道这个方法主要是当序列化过滤器不为空的时候触发该过滤器。

其中反序列化过滤器就为serialFilter属性值,跟进一下。

这是一个ObjectInputFilter接口,根据注释我们知道从流中读取类的类描述符和类的过滤器,可以不进行配置。

我们看看该类的构造方法:

默认会对serialFilter属性进行赋值操作,跟进ObjectInputFilter.Config.getSerialFilter()方法的调用。

获取的是ObjectInputFilter中的内部静态类ConfigserialFilter属性

跟下来回到filterCheck方法的分析。

首先就会判断是否具有serialFilter这个过滤器,如果不为空,将会调用过滤器的checkInput方法进行过滤处理,传入了clazz / arrayLength / depth等信息。

这个方法返回的是一个ObjectInputFilter.Status,这是一个枚举类型。

接下来回到filterCheck方法。

如果返回的状态为null/REJECTED两个之一,将会抛出异常。

所以,对于过滤器的设置,我们可以通过创建一个ObjectInputFilter实例,并重写他的checkInput方法,在其中实现我们的过滤逻辑,之后通过调用ObjectInputStream#setInternalObjectInputFilter进行为stream添加过滤器。

ObjectInputFilter$Config

在这个类中,存在有一个静态代码块。

在调用该类的时候就会为serialFilter属性赋值,跟进到configuredFilter属性的来源。

主要是获取jdk.serialFilter属性值,之后通过调用createFilter方法进行过滤器的创建。

跟进一下createFilter方法的调用。

这个方法将会调用ObjectInputFilter.Config.Global.createFilter方法进行创建。

ObjectInputFilter$Config$Global

接着上面的分析,我们跟进该类的createFilter方法

将传入的JEP规则字符串var0传入Global内部静态类的构造方法中,创建了一个Golbal对象,进行返回,所以前面在ObjectInputStream类的构造方法中主要是为serialFilter赋值的是一个Global类。

查看官方文档,我们知道JEP 290的编写规则为:

  1. 如果模式以“!”开头,如果模式的其余部分匹配,则该类被拒绝,否则被接受
  2. 如果模式包含“/”,则“/”之前的非空前缀是模块名称。如果模块名称与类的模块名称匹配,则剩余模式与类名称匹配。如果没有“/”,则不比较模块名称。
  3. 如果模式以“.**”结尾,则它匹配包和所有子包中的任何类
  4. 如果模式以“.*”结尾,它匹配包中的任何类
  5. 如果模式以“*”结尾,它匹配任何以该模式为前缀的类
  6. 如果模式等于类名,则匹配
  7. 否则,状态未定

  • If the pattern starts with "!", the class is rejected if the rest of the pattern matches, otherwise it is accepted
  • If the pattern contains "/", the non-empty prefix up to the "/" is the module name. If the module name matches the module name of the class then the remaining pattern is matched with the class name. If there is no "/", the module name is not compared
  • If the pattern ends with ".**" it matches any class in the package and all subpackages
  • If the pattern ends with ".*" it matches any class in the package
  • If the pattern ends with "*", it matches any class with the pattern as a prefix
  • If the pattern is equal to the class name, it matches
  • Otherwise, the status is undecided

接下来看看Global构造方法中是如何进行解析的。

首先是通过传入的规则var1,将其根据;进行分割,并初始化filters属性为ArrayList数组。

首先判断是否以*结尾,进而判断是否是.*结尾,如果是以!开头的话成功匹配的话,将会通过lambada的格式调用this.filters.addStatus放置于filters属性中,这里举个例子就行了,后面就也就是同样的格式,进行filters属性的添加

我们看看filters属性是个什么东西。

这是一个函数列表。

这样成功设置了过滤器,当我们调用的时候将会调用

代码语言:javascript
复制
代码语言:javascript
复制
ObjectInputStream#filterCheck
    ObjectInputFilter$Config$Global#checkInput

主要是根据遍历filters属性通过反序列化的类进行获取对应的Status状态

过滤器

全局过滤器

通过前面的分析,我们可以知道在ObjectInputFilter$Config类中属性configuredFilter中获取了jdk.serialFilter属性值,这里就是全局过滤器。

对于该属性值的设置有两种方式:

  1. 配置JVM的jdk.serialFilter;
  2. 配置 %JAVA_HOME%\conf\security\java.security中的jdk.serialFilter字段。

局部过滤器

同样有着两种方法进行设置

  1. 在创建ObjectInputStream对象之后通过调用其 setInternalObjectInputFilter方法进行设置;
  2. 又或者是调用 Config#setObjectInputFilter方法进行设置。
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-10-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeBuf 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • JEP290是Java官方提供的一套来防御反序列化的机制,其核心在于提供了一个ObjectInputFilter接口,通过设置filter对象,然后在反序列化(ObjectInputStream#readObject)的时候触发filter的检测.
  • 处理
  • 我这里的JDK是 8u202版本。
    • ObjectInputStream
      • ObjectInputFilter$Config
        • ObjectInputFilter$Config$Global
        • 过滤器
        • 全局过滤器
          • 局部过滤器
          相关产品与服务
          文件存储
          文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档