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
编写恶意类
测试:
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
常规的Java字节码的执行,但是需要开启
Feature.SupportNonPublicField
,较鸡肋利用JNDI注入,但需要服务器出网
不用出网也不用开启
Feature.SupportNonPublicField
,但对JDK版本有限制
调用链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
方式调用getterref是fastjson特有的JSONPath语法,用来引用之前出现的对象
Last updated