javaCC链-CC1
1. 环境搭建
JDK版本:jdk8u65
commons-collections 3.2.1
Maven依赖:
<dependencies>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
</dependencies>
2. CC1链的核心思路
- 有个“万能遥控器”——
InvokerTransformer- 这个类有个 transform 方法,可以用来“反射”调用任何你想要的方法,比如 Runtime.getRuntime().exec("calc"),就能弹出计算器。
- 找个“帮手”能帮你自动按下遥控器——TransformedMap
- 这个 Map 可以在你往里面放数据或者修改数据时,自动调用你指定的 transform 方法。
- 把遥控器装进帮手手里
- 用 TransformedMap.decorate(map, null, invokerTransformer) 把
InvokerTransformer作为 valueTransformer 装进去。
- 用 TransformedMap.decorate(map, null, invokerTransformer) 把
- 找个“触发器”让帮手动起来
- 只要有人调用 TransformedMap 的 setValue 方法(比如遍历 entrySet 的时候),就会自动触发 transform,也就是执行你想要的命令。
- 最后一步:让这些东西在反序列化时自动触发
- Java 反序列化时会自动调用某些方法(比如 readObject),而
AnnotationInvocationHandler这个类在反序列化时会遍历 Map 并 setValue,从而触发整个链条。
- Java 反序列化时会自动调用某些方法(比如 readObject),而
3. 分析
cc1链起点是commons-collections包的Transformer接口,这个接口的transform方法接收一个对象作为参数
3.1. 万能遥控器—— InvokerTransformer
InvokerTransformer 是 commons-collections 3.2.1 包中的一个类,也是我们的入口类,其全名是:
org.apache.commons.collections.functors.InvokerTransformer
3.1.1. 作用
它可以让你通过 transform 方法,反射调用任何你想要的方法
在 CC1 链中,它就是“遥控器”,用来执行恶意命令的关键
3.1.2. 例子
// 创建一个 InvokerTransformer,指定调用 exec 方法,参数是 "calc"
InvokerTransformer transformer = new InvokerTransformer(
"exec", new Class[]{String.class}, new Object[]{"calc"}
);
当你调用 transformer.transform(Runtime.getRuntime()) 时,它就会执行:Runtime.getRuntime().exec("calc"); 触发计算器
3.2. TransformedMap-按下遥控器的帮手
它是一个可以在存取数据时自动对 key 或 value 进行“变换处理”的 Map。
这个 Map 可以在你往里面放数据或者修改数据时,自动调用你指定的 transform 方法。
3.2.1. 作用
- 当你往 TransformedMap 里 put、setValue 或修改数据时,它会自动调用你指定的 Transformer,把 key 或 value 变换成你想要的样子。
- 你可以单独指定 keyTransformer(处理 key)和 valueTransformer(处理 value)
- 攻击者把 valueTransformer 设置成恶意的 InvokerTransformer
- 只要有人往这个 Map 里 setValue 或 put,就会自动执行 transform 方法,从而执行恶意代码
-
当你调用 put(key, value) 或 setValue(value) 时,TransformedMap 会自动调用你传进去的 valueTransformer 的 transform(value) 方法,把 value 先“加工”一下,再存进去。
-
如果你传进去的 valueTransformer 是一个恶意的 InvokerTransformer,那么 transform 方法里就会执行你想要的恶意操作。
你可以把 TransformedMap 想象成一个“智能快递柜”:
-
你往柜子里放快递(put/setValue),柜子会自动帮你消毒(transform)。
-
你指定的消毒方式(Transformer)是什么,柜子就怎么处理。
org.apache.commons.collections.functors.InvokerTransformer
可以看到我们这个payload就是先new了一个 InvokerTransformer。
小框框中的是他的三个参数:iMethodName,iParamTypes,iArgs都是可控的
然后通过它的transform方法使用了反射来调用input的方法,
且传入的这个input对象也是可控的
我们可以通过直接利用invoketransformer的代码,执行过后就会触发计算器
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.InvokerTransformer;
public class CC1 {
public static void main(String[] args) {
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}).transform(Runtime.getRuntime());
}
}
然后我们去找一个其它的类有transform方法,并且传入的Object是可控的,然后我们只要把这个Object设为InvokeTransformer即可,我们全局搜索transform方法,能够发现很多类都是有transform方法的,我们这里先研究的是CC1,所以我们直接看 TransformerMap 类
然后我们查找用法,看有那些类也用了这个 transform(object)
在 TransformedMap 中的checkSetValue方法中调用了transform,valueTransformer是构造的时候赋的值,再看构造函数
构造函数是一个protected,所以不能让我们直接实例赋值,只能是类内部构造赋值,找哪里调用了构造函数
这里找到了一个静态方法,这里我们就能控制参数了








