Java安全-深入BeanValidation的RCE漏洞
字数 1676 2025-08-24 23:51:23

Java安全:深入Bean Validation的RCE漏洞分析与防御

1. 漏洞概述

Bean Validation是Java EE/Jakarta EE规范(JSR 303/JSR 380)中定义的一套基于注解的数据验证框架。该漏洞存在于错误消息处理机制中,当用户可控的Java Bean属性被连接到验证错误信息中时,其中的EL表达式会被执行,导致远程代码执行(RCE)。

关键特征:

  • 使用Java Bean Validation进行参数验证
  • 验证用户可控的Java Bean
  • 不合法属性回显到错误消息中
  • 错误消息中的EL表达式被执行

2. Bean Validation基础

2.1 核心概念

Bean Validation通过注解方式简化数据验证:

  • 内置注解:@NotNull, @Min, @Max, @Pattern
  • 自定义注解:可创建特定业务规则的验证注解
  • 统一验证:避免大量if-else判断,简化代码

2.2 典型实现

Hibernate Validator是Bean Validation的参考实现,包含在:

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.1.2.Final</version>
</dependency>

3. 漏洞复现与分析

3.1 漏洞环境搭建

示例代码结构:

  1. 自定义验证注解@IpAddress
@Target({ FIELD })
@Retention(RUNTIME)
@Constraint(validatedBy = IpAddressValidator.class)
public @interface IpAddress {
    String message() default "";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default { };
}
  1. 验证器实现:
public class IpAddressValidator implements ConstraintValidator<IpAddress, String> {
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        // 验证逻辑...
        if(!isValid){
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate("invalid ip :" + message)
                   .addConstraintViolation();
        }
        return isValid;
    }
}
  1. Controller层验证:
@PostMapping("/validateBody")
ResponseEntity<String> validateBody(@Valid @RequestBody Input input) {
    return ResponseEntity.ok("valid");
}
  1. 全局异常处理:
@ExceptionHandler(MethodArgumentNotValidException.class)
public Object errorHandler(MethodArgumentNotValidException e) {
    Map<String,String> error = new HashMap<>();
    for (FieldError fieldError : e.getBindingResult().getFieldErrors()) {
        error.put(fieldError.getField(),fieldError.getDefaultMessage());
    }
    return JSON.toJSONString(error);
}

3.2 漏洞触发流程

  1. 用户提交恶意输入如${1+1}
  2. 验证失败时,错误信息包含用户输入
  3. Hibernate Validator处理错误消息时解析EL表达式
  4. 表达式被执行,结果插入到返回信息中

3.3 技术原理分析

关键调用栈:

ElTermResolver.interpolate()
InterpolationTerm.interpolate()
ResourceBundleMessageInterpolator.interpolate()
AbstractMessageInterpolator.interpolateExpression()
AbstractMessageInterpolator.interpolateMessage()
MessageSourceMessageInterpolator.interpolate()
LocaleContextMessageInterpolator.interpolate()
AbstractValidationContext.addConstraintFailure()

核心问题在于org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator#interpolateMessage方法:

  • 先处理参数插值({})
  • 再处理EL表达式插值(${})
  • 表达式由ElTermResolver执行

4. 相关CVE分析

4.1 CVE-2018-16621 (Nexus Repository Manager)

影响版本:3.x - 3.13

漏洞点

  • org.sonatype.nexus.coreui.UserXO
  • 使用@RolesExist自定义验证注解
  • 验证器RolesExistValidator存在EL注入

修复方式

if (roles != null && roles.matches(".*[${}]+.*")) {
    throw new IllegalArgumentException("Invalid roles");
}

4.2 CVE-2020-10693 (Hibernate Validator)

漏洞描述

  • Hibernate Validator 6.0.15.Final之前版本
  • 可解析错误格式的EL表达式如exp|$\A{2*333}|
  • 由于TokenCollector#parse方法的解析缺陷

关键代码路径

  1. MessageState#handleELDesignator设置状态为ELState
  2. 遇到\时进入EscapedState
  3. 后续字符使状态返回ELState
  4. 最终构造出合法EL表达式

4.3 CVE-2020-10204 (Nexus绕过)

绕过方式

  • 使用exp|$\A{2*333}|绕过CVE-2018-16621的修复
  • 利用了CVE-2020-10693的解析缺陷

修复方式

  • 增加额外的replaceAll过滤

5. 防御措施

5.1 开发层面

  1. 禁用EL表达式
Validator validator = Validation.byDefaultProvider()
    .configure()
    .messageInterpolator(new ParameterMessageInterpolator())
    .buildValidatorFactory()
    .getValidator();
  1. 严格输入过滤
if (input.matches(".*[${}]+.*")) {
    throw new IllegalArgumentException("Invalid input");
}
  1. 自定义消息插值器
public class SafeMessageInterpolator extends ResourceBundleMessageInterpolator {
    @Override
    public String interpolate(String message, Context context) {
        // 过滤EL表达式
        return super.interpolate(sanitize(message), context);
    }
}

5.2 运维层面

  1. 升级到安全版本:

    • Hibernate Validator ≥ 6.0.15.Final
    • Nexus Repository Manager ≥ 3.21.2
  2. WAF规则:

    • 拦截包含${}的请求

6. 总结

Bean Validation的RCE漏洞揭示了框架设计中的安全隐患:

  1. 错误消息处理不应执行用户输入
  2. 表达式语言引擎需要严格沙箱限制
  3. 多层防御比单一修复更有效

开发者应当:

  • 了解框架的安全机制
  • 谨慎处理用户输入的回显
  • 及时更新依赖组件版本
  • 实施深度防御策略
Java安全:深入Bean Validation的RCE漏洞分析与防御 1. 漏洞概述 Bean Validation是Java EE/Jakarta EE规范(JSR 303/JSR 380)中定义的一套基于注解的数据验证框架。该漏洞存在于错误消息处理机制中,当用户可控的Java Bean属性被连接到验证错误信息中时,其中的EL表达式会被执行,导致远程代码执行(RCE)。 关键特征: 使用Java Bean Validation进行参数验证 验证用户可控的Java Bean 不合法属性回显到错误消息中 错误消息中的EL表达式被执行 2. Bean Validation基础 2.1 核心概念 Bean Validation通过注解方式简化数据验证: 内置注解: @NotNull , @Min , @Max , @Pattern 等 自定义注解:可创建特定业务规则的验证注解 统一验证:避免大量if-else判断,简化代码 2.2 典型实现 Hibernate Validator是Bean Validation的参考实现,包含在: 3. 漏洞复现与分析 3.1 漏洞环境搭建 示例代码结构: 自定义验证注解 @IpAddress : 验证器实现: Controller层验证: 全局异常处理: 3.2 漏洞触发流程 用户提交恶意输入如 ${1+1} 验证失败时,错误信息包含用户输入 Hibernate Validator处理错误消息时解析EL表达式 表达式被执行,结果插入到返回信息中 3.3 技术原理分析 关键调用栈: 核心问题在于 org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator#interpolateMessage 方法: 先处理参数插值( {} ) 再处理EL表达式插值( ${} ) 表达式由 ElTermResolver 执行 4. 相关CVE分析 4.1 CVE-2018-16621 (Nexus Repository Manager) 影响版本 :3.x - 3.13 漏洞点 : org.sonatype.nexus.coreui.UserXO 类 使用 @RolesExist 自定义验证注解 验证器 RolesExistValidator 存在EL注入 修复方式 : 4.2 CVE-2020-10693 (Hibernate Validator) 漏洞描述 : Hibernate Validator 6.0.15.Final之前版本 可解析错误格式的EL表达式如 exp|$\A{2*333}| 由于 TokenCollector#parse 方法的解析缺陷 关键代码路径 : MessageState#handleELDesignator 设置状态为ELState 遇到 \ 时进入 EscapedState 后续字符使状态返回 ELState 最终构造出合法EL表达式 4.3 CVE-2020-10204 (Nexus绕过) 绕过方式 : 使用 exp|$\A{2*333}| 绕过CVE-2018-16621的修复 利用了CVE-2020-10693的解析缺陷 修复方式 : 增加额外的 replaceAll 过滤 5. 防御措施 5.1 开发层面 禁用EL表达式 : 严格输入过滤 : 自定义消息插值器 : 5.2 运维层面 升级到安全版本: Hibernate Validator ≥ 6.0.15.Final Nexus Repository Manager ≥ 3.21.2 WAF规则: 拦截包含 ${ 和 } 的请求 6. 总结 Bean Validation的RCE漏洞揭示了框架设计中的安全隐患: 错误消息处理不应执行用户输入 表达式语言引擎需要严格沙箱限制 多层防御比单一修复更有效 开发者应当: 了解框架的安全机制 谨慎处理用户输入的回显 及时更新依赖组件版本 实施深度防御策略