利用TemplatesImpl执行字节码在实战中的踩坑记录
在平时,无论是JNDI注入,还是反序列化,只要涉及到不出网的场景,TemplatesImpl的利用就很广泛,这里记录一个在实战中遇到的踩坑记录,篇幅不多贵在记录。
假设当前服务器存在反序列化漏洞,不出网,当你兴高采烈的拿着工具去打的时候发现怎么也打不通,内存马上不去,回显也没有,这是怎么回事呢?且看下文。
既然需要使用TemplatesImpl加载字节码,那么就需要生成恶意类的Bytecode
这里我们再温习一下,最终在getTransletInstance方法处加载字节码到jvm,并调用newInstance实例化触发恶意代码的加载
网上的各种工具,基本上都使用了javassist框架进行恶意类的生成,这里以TomcatEcho为例,大多数工具代码都类似下面的写法,创建类,添加方法,生成ByteCode
问题就出在输出ByteCode的过程中,当调用ClassPool.getDefault()
的过程中,会初始化ClassFile,根据某些不同版本特定存在的类来判断当前环境的MAJOR_VERSION
(Ps:这里的反编译有点问题,从上到下ver其实是依次从49到55),这个MAJOR_VERSION
其实就是我们java的主版本号从49-55分别为jdk1.5到jdk11
因此这就很有意思了,这意味着使用javassist生成的字节码的属性信息和当前java运行环境有关
假设当前服务器是一个jdk1.6跑着的tomcat服务,你拿工具打,那很显然jdk1.6并不能运行1.8版本下编译的程序,那怎么办呢?其实很简单修改这个MAJOR_VERSION
就行,只要这个属性的数值小于或等于当前运行的java环境那就能过检查并运行
而javassist本身也提供了对应的api去帮助我们修改,比如我们需要生成1.6能运行的字节码,我们只需要在原来的基础上加上clazz.getClassFile().setMajorVersion(50);
即可
那如果是asm框架怎么办,就更简单了,创建类的时候在第一个输入写上对应主版本号即可