内容纲要

前言

上一章我们分析了 CommonsCollections2 Payload , 该 Payload 构造的十分巧妙 , 通过组合 JAVAssist 字节码增强类库 和 PriorityQueue优先级队列 两种技术实现了任意代码执行 .

本章我们来分析 CommonsCollections3 的 Payload 是如何构造与利用的.


CommonsCollections3

CommonsCollections3 Payload 简介

查看 CommonsCollections3 源码 , 一股熟悉的气息扑面而来.

整个 Payload 的架构是 CommonsCollections1 的 . 只是系统命令执行的部分换成了使用 JAVAssist 来生成恶意类字节码 , 类似 CommonsCollections2 . 认真调试过 CommonsCollections1 和 CommonsCollections2 的师傅估计能直接把整个函数调用链猜出来 .

那么废话不多说 , 开始i分析吧.


CommonsCollections3 Payload 复现

按照老规矩 , 先来复现一下该利用链.

复现环境 : JDK1.7_67 + Tomcat7 + CommonsCollections-3.1

  1. 指定 YSoSerial 参数为 CommonsCollections3 "mate-calc" 并生成 Payload , 该 Payload 被执行时会弹出计算器.

  2. 加载 CommonsCollections-3.1 组件并启动 Tomcat7 , 将本地生成的 Payload 通过 Curl 工具发出.

    curl "http://localhost:8080/webdemotest_war_exploded/demotest" --data-binary @/tmp/payload.ser

成功弹出计算器 , 该利用链复现成功.


CommonsCollections3 Payload 构造


Gadgets.createTemplatesImpl(command)

ACC3 的第一步与 ACC2 完全相同 , 都是利用 JAVAssist 技术来动态生成携带恶意命令的字节码 , 并将该字节码注入到返回的 TemplatesImpl 实例对象的 _bytecode 字段中

生成的恶意字节码文件如下:

恶意代码被填充到静态代码块中 , 当类被初始化时 , 会执行静态代码块中的内容 , 进而执行恶意代码


ChainedTransformer - ConstantTransformer - InstantiateTransformer 反射调用链

首先会初始化一个 ChainedTransformer 实例对象 , 在分析 ACC1 利用链时我们得知可以通过 LazyMap.get() 方法来调用 ChainedTransformer.transform() 方法 , 进而进入 InvokerTransformer.transform() 反射调用链.

然后代码会构造真正的函数调用链 , 这里明显与 ACC1 不同 , 它没有获取 InvokerTransformer 实例对象 , 而是获取了 InstantiateTransformer 对象 , 并且引入了一个我们没见过的 TrAXFilter 类.

那么 , 现在的问题就被划分为了两块 :

  • TrAXFilter 类定义是什么 ?
  • InstantiateTransformer 类定义是什么 ?

com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter.class

根据注释得知该类是XMLFilterImpl框架的扩展类 , 我们来看一看类的定义.

这部分思路已经很明显了 , TrAXFilter 构造方法中变量 _transformer 是通过 (TransformerImpl) templates.newTransformer(); 来赋值的 , 而当调用 TransformerImpl.newTransformer() 方法时 , 与 ACC2 的调用链完全一致 , 如下图所示 :

ACC3 中则更加巧妙 , 我们不再需要去构造优先级队列( PriorityQueue ) , 而可以通过 TrAXFilter 类的构造方法 TrAXFilter(Templates templates) 直接调用 TemplatesImpl.newTransformer() 方法

那么有没有方法可以在实例化 TrAXFilter 类的同时调用指定的构造方法呢 ? 答案就是 InstantiateTransformer.class !


org.apache.commons.collections.functors.InstantiateTransformer.class

InstantiateTransformer.transform() 方法实现了生成指定类的对象并调用指定的构造方法.

根据上文的分析 , 我们希望可控的三个参数 input , this.iParamType , this.Args 分别对应如下值

  • input : com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter.Class
  • this.iParamType : javax.xml.transform.Templates.Class
  • this.args : 通过 JAVAssist 动态生成的恶意 templatesImpl 对象

现在再看这部分的构造 , 都一一对应上了.


通过动态代理来调用 LazyMap.get() 方法.

我们现在需要调用 InstantiateTransformer.transform() 方法 , 这里还是利用了 LazyMap.get()

在分析 ACC1 时我就讲过了 YSoSerial 中如何调用 LazyMap.get() 方法 :

通过 JDK原生动态代理 , 拦截所有对 Map.Class 接口中方法的访问请求 , 并将请求转发到 AnnotationInvocationHandler.invoke() 方法中 , 该方法中会调用 this.memberValues.get() 方法 , 而此时 this.memberValues 会指向 LazyMap , 所以实际调用的是 LazyMap.get() 方法

这里和 ACC1 完全相同 , 如果不明白上文我在说什么 , 可以参考 Java 反序列化漏洞(7) – 解密 YSoSerial : CommonsCollections1 POP Chains


通过反射修改 transformerChain 对象的 iTransformers 字段

这一步与 ACC1 中相同 , 是为了将真正的恶意代码注入函数调用链 .

至此 , CommonsCollections3 Payload 就构造完成了 , 其实用的都是 ACC1 和 ACC2 的知识点 .


CommonsCollections3 Payload 利用

利用方面其实也没啥好说的 , 该说的点都在前面两章说完了 .

JDK原生动态代理的转发

这部分不明白的师傅可以参考 Java 反序列化漏洞(7) – 解密 YSoSerial : CommonsCollections1 POP Chains


加载恶意字节码 , 执行静态代码块内容

这部分不明白的师傅可以参考 Java 反序列化漏洞(8) – 解密 YSoSerial : CommonsCollections2 POP Chains


总结

Apache CommonsCollections3 Payload 的构造基于 CommonsCollection1 Payload 和 CommonsCollections2 Payload , 没有什么新的知识点 , 分析起来比较轻松 .

本章内容比较简单 , 如果您认真分析过 ACC1 和 ACC2 , 那么分析 ACC3 没有任何难度 .

最近一直在出差 , 基本没啥空余时间 . 不过 ACC 的利用链后面也没啥难点了 , 我会尽快把这部分内容结束 , 去研究一下其他的利用链~~~

最后修改日期:2020年9月13日

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。