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 漏洞环境搭建
示例代码结构:
- 自定义验证注解
@IpAddress:
@Target({ FIELD })
@Retention(RUNTIME)
@Constraint(validatedBy = IpAddressValidator.class)
public @interface IpAddress {
String message() default "";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
- 验证器实现:
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;
}
}
- Controller层验证:
@PostMapping("/validateBody")
ResponseEntity<String> validateBody(@Valid @RequestBody Input input) {
return ResponseEntity.ok("valid");
}
- 全局异常处理:
@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} - 验证失败时,错误信息包含用户输入
- Hibernate Validator处理错误消息时解析EL表达式
- 表达式被执行,结果插入到返回信息中
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方法的解析缺陷
关键代码路径:
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表达式:
Validator validator = Validation.byDefaultProvider()
.configure()
.messageInterpolator(new ParameterMessageInterpolator())
.buildValidatorFactory()
.getValidator();
- 严格输入过滤:
if (input.matches(".*[${}]+.*")) {
throw new IllegalArgumentException("Invalid input");
}
- 自定义消息插值器:
public class SafeMessageInterpolator extends ResourceBundleMessageInterpolator {
@Override
public String interpolate(String message, Context context) {
// 过滤EL表达式
return super.interpolate(sanitize(message), context);
}
}
5.2 运维层面
-
升级到安全版本:
- Hibernate Validator ≥ 6.0.15.Final
- Nexus Repository Manager ≥ 3.21.2
-
WAF规则:
- 拦截包含
${和}的请求
- 拦截包含
6. 总结
Bean Validation的RCE漏洞揭示了框架设计中的安全隐患:
- 错误消息处理不应执行用户输入
- 表达式语言引擎需要严格沙箱限制
- 多层防御比单一修复更有效
开发者应当:
- 了解框架的安全机制
- 谨慎处理用户输入的回显
- 及时更新依赖组件版本
- 实施深度防御策略