简单复习下JEP290

admin 2023年11月8日02:09:50评论21 views字数 2498阅读8分19秒阅读模式


一、JEP290简介




1.JEP290 JDK版本

JEP290机制在2016年被提出,本身为Java9的特性,官方决定向下引进该增强机制,分别对6、7、8进行支持:8u121,7u131,6u141。

2.JEP290包含的机制

(1)提供一个限制反序列化类的机制,白名单或者黑名单

(2)限制反序列化的深度和复杂度

(3)为RMI远程调用对象提供了一个验证类的机制

(4)定义一个可配置的过滤机制,比如可以通过配置properties文件的形式来定义过滤器

上面的这些是参考网上文章直接复制过来,乍一看模棱两可。

3.JEP290防御原理

(1)原始反序列化防御

JEP290之前,对放序列化的防御也都只是缓解,方法是写一个ObjectInputStream 的子类,这个子类要重写 resolveClass(),并在这个方法中验证一个类是否能被加载,也就是实现白名单和黑名单 。在白名单中,只能让可接受的类被反序列化解析,其他的类会被阻止。黑名单则是收集已知会造成问题的类,然后把它们全部阻止。

(2)JEP290防御

https://docs.oracle.com/javase/9/docs/api/java/io/*.html

核心原理是,反序列化过滤基于 java.io.ObjectInputFilter接口,这个接口提供一种配置能力,目的是在反序列化过程中验证输入的数据。通过ObjectInputFilter接口参数:Status.ALLOWED , Status.REJECTED或者 Status.UNDECIDED 去检查输入数据的状态。比如,如果想用黑名单的形式,那么遇到一些特殊的类就要返回Status.REJECTED,并且如果返回Status.UNDECIDED的话,就是允许反序列化。另外一方面,如果想用白名单的形式,那么当返回Status.ALLOWED的时候,就代表匹配到了白名单里面的类。

简单复习下JEP290

此外,过滤器也被允许访问一些反序列化数据中的一些其他信息,比如,在反序列化过程中类数组中数组的长度 arrayLength ,每一个内置对象的深度 depth,当前对象的引用数量 references ,当前二进制流占用空间的大小 streamBytes 。这些提供了关于输入流更多的细粒度信息,并且在每一次匹配中都会返回相应的状态。

简单复习下JEP290

 

4.JEP290配置过滤器方式

(1) process-wide filter 全局过滤器(进程级过滤器)

启动Java应用时添加命令行参数

-Djdk.serialFilter=<白名单类1>;<白名单类2>;!<黑名单类>

或者设置Java系统属性(Java 6,7,8)

$JAVA_HOME/jre/lib/security/java.security(官方的是错的)

简单复习下JEP290

 

或者启动Java应用时设置

-Djava.security.properties=<黑白名单配置文件名>

全局过滤器一旦被设置,将无法被绕过

(2) custom filter 用户自定义过滤器

可以覆盖进程级过滤器!

当程序员很明确知道他想要反序列化的类是在哪个具体的包下,或者具体的类。需要程序员手动修改应用程序级别的代码。

示例代码:

ObjectInputFilter filesOnlyFilter = ObjectInputFilter.Config.createFilter("de.mogwailabs.Example;!*");

(3) built-in filters 内置过滤器

专门用于RMI,现在习惯用 Distributed Garbage Collection (DGC) 

jdk 9 也引进了一个内置的过滤器,配置这个过滤器主要用于RMI和DGC 。RMI Registry 和 DGC的内置过滤器是白名单的形式,白名单包含了服务器能够执行的类。

JEP290中对RMI设置了默认的过滤器(sun.rmi.registry.RegistryImpl#registryFilter)

简单复习下JEP290

JDK会判断反序列化的类以及父类是否在白名单中(仅用于RmiRegistry)

相对应的DGCImple中也有 sun.rmi.transport.DGCImpl#checkInput

简单复习下JEP290

可以看到在java.security中是有说明配置了的,用户如果想自定义可以选择取消ava.security注释添加自己自定义即可

简单复习下JEP290

PS:补充一个之前一直不清楚的小知识DGC

分布式辣鸡回收

在Java虚拟机中,对于一个本地对象,只要不被本地Java虚拟机中的任何变量引用,它就可以被垃圾回收器回收了。

而对于一个远程对象,不仅会被本地Java虚拟机中的变量引用还会被远程引用。如将远程对象注册到Rregistry时,Registry注册表就会持有它的远程引用。

RMI框架采用分布式垃圾收集机制(DGC,Distributed Garbage Collection)来管理远程对象的生命周期。DGC的主要规则是,只有当一个远程对象不受任何本地引用和远程引用,这个远程对象才会结束生命周期。当客户端获得了一个服务器端的远程对象存根时,就会向服务器发送一条租约通知,告诉服务器自己持有这个远程对象的引用了。此租约有一个租约期限,租约期限可通过系统属性java.rmi.dgc.leaseValue来设置,以毫秒为单位,其默认值为600 000毫秒。如果租约到期后服务器端没有继续收到客户端新的租约通知,服务器端就会认为这个客户已经不再持有远程对象的引用。

因此可以通过与DGC通信的方式发送恶意payload让服务端进行反序列化,从而执行任意命令。


二、参考链接




https://xz.aliyun.com/t/3210

http://openjdk.java.net/jeps/290

https://paper.seebug.org/1251/

https://xz.aliyun.com/t/8706

https://cert.360.cn/report/detail?id=add23f0eafd94923a1fa116a76dee0a1


情绪很多的时候说明你很闲


原文始发于微信公众号(赛博少女):简单复习下JEP290

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年11月8日02:09:50
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   简单复习下JEP290http://cn-sec.com/archives/820333.html

发表评论

匿名网友 填写信息