JEP290

admin 2024年1月19日11:48:15评论19 views字数 5237阅读17分27秒阅读模式

JEP 290

JEP:JDK Enhancement Proposal JDK增强建议 ;JEP是一个JDK核心技术相关的增强建议文档

JEP 290主要解决反序列化安全问题。 JEP 290 在 JDK 9 中加入,但在 JDK 6,7,8 一些高版本中也添加了

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)

JEP主要通过

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

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

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

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

下面通过运行两个jdk版本运行rmi例子做对比验证

rmi例子

1.定义rmi接口

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public interface Hello extends Remote {
    String hello() throws RemoteException;;
    String hello(String name) throws RemoteException;;
    String hello(Object object) throws RemoteException;;
}

2.实现接口

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class HelloImpl extends UnicastRemoteObject implements Hello {
    protected HelloImpl() throws RemoteException {
    }

    @Override
    public String hello() {
        return "Hello world";
    }

    @Override
    public String hello(String name) {
        return "Hello world"+name;
    }

    @Override
    public String hello(Object object) {
        System.out.println(object);
        return "Hello world"+object.toString();
    }
}

3.注册服务,绑定接口在端口上

import java.io.ObjectInputStream;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;

public class RMIServier {
    public static String HOST = "127.0.0.1";
    public static int PORT = 1099;
    public static String RMI_PATH = "/hello";
    public static final String RMI_NAME = "rmi://" + HOST + ":" + PORT + RMI_PATH;

    public static void main(String[] args) {
        try {
            // 注册RMI端口
            LocateRegistry.createRegistry(PORT);
            // 创建一个服务
            Hello hello = new HelloImpl();
            // 服务命名绑定
            Naming.rebind(RMI_NAME, hello);

            System.out.println("启动RMI服务:" + RMI_NAME);
           // ObjectInputStream o;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

下面通过运行两个不同jdk版本运行rmi例子做对比验证

当jdk 为1.7u80

输入java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit 127.0.0.1 1099 CommonsCollections1 calc

就会弹出计算器

当Jdk为1.8u151

输入命令java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit 127.0.0.1 1099 CommonsCollections1 calc

就会显示
十二月 07, 2022 1:53:20 下午 java.io.ObjectInputStream filterCheck
信息: ObjectInputFilter REJECTED: class sun.reflect.annotation.AnnotationInvocationHandler, array length: -1, nRefs: 8, depth: 2, bytes: 297, ex: n/a

JEP290实现对反序列化漏洞进行预防呢

JEP 290 进行过滤的具体实现方法是在 objectInputStream 类中增加了一个serialFilter属性和一个 filterChcek 函数,两者搭配来实现过滤的
每当进行一次反序列化操作时,底层就会根据filter中的内容来进行判断,从而防止恶意的类进行反序列化操作。此外,还可以限制反序列化数据的信息,比如数组的长度、字节流长度、字节流深度以及使用引用的个数等。filter返回accept,reject或者undecided几个状态,然后用户根据状态进行决策
ObjectInputStream这是Java.io中一个输入流,

public ObjectInputStream(InputStream in) throws IOException {
        verifySubclass();
        bin = new BlockDataInputStream(in);
        handles = new HandleTable(10);
        vlist = new ValidationList();
        serialFilter = ObjectInputFilter.Config.getSerialFilter();//获取配置文件序列化配置
        enableOverride = false;
        readStreamHeader();
        bin.setBlockDataMode(true);
    }
 private void filterCheck(Class<?> clazz, int arrayLength)
            throws InvalidClassException 
{
        if (serialFilter != null) {
            RuntimeException ex = null;
            ObjectInputFilter.Status status;
            try {
                status = serialFilter.checkInput(new FilterValues(clazz, arrayLength,
                        totalObjectRefs, depth, bin.getBytesRead()));
            } catch (RuntimeException e) {
                // Preventive interception of an exception to log
                status = ObjectInputFilter.Status.REJECTED;
                ex = e;
            }
            if (status == null  ||
                    status == ObjectInputFilter.Status.REJECTED) {
                // Debug logging of filter checks that fail
                if (Logging.infoLogger != null) {
                    Logging.infoLogger.info(
                            "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",
                            status, clazz, arrayLength, totalObjectRefs, depth, bin.getBytesRead(),
                            Objects.toString(ex, "n/a"));
                }
                InvalidClassException ice = new InvalidClassException("filter status: " + status);
                ice.initCause(ex);
                throw ice;
            } else {
                // Trace logging for those that succeed
                if (Logging.traceLogger != null) {
                    Logging.traceLogger.finer(
                            "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",
                            status, clazz, arrayLength, totalObjectRefs, depth, bin.getBytesRead(),
                            Objects.toString(ex, "n/a"));
                }
            }
        }
    }

可以通过配置文件设置一个黑白名单,允许(禁止)哪些类反序列化
(1)通过设置jdk.serialFilter这个System.property
(2)直接通过conf/security/java.properties文件进行配置

绕过jep290以及分析具体过滤代码就暂时不想看了

参考:https://cloud.tencent.com/developer/article/1850810
https://nosec.org/home/detail/4846.html
https://paper.seebug.org/454/
https://blog.csdn.net/u011721501/article/details/78555246

这也是22年学习java安全过程中搜集相关资料,然后实践过相关内容,仅作学习记录

原文始发于微信公众号(天才少女Alpha):JEP290

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年1月19日11:48:15
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JEP290https://cn-sec.com/archives/2408755.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息