CVE-2022-22963
https://github.com/vulhub/vulhub/blob/master/spring/CVE-2022-22963/README.zh-cn.md
概述
Spring Cloud Function SpEL表达式命令注入(CVE-2022-22963)
Spring Cloud Function 提供了一个通用的模型,用于在各种平台上部署基于函数的软件,包括像 Amazon AWS Lambda 这样的 FaaS(函数即服务,function as a service)平台。
影响版本:3.0.0 <= Spring Cloud Function <= 3.2.2
分析
org.springframework.cloud.function.context.config.RoutingFunction#route
private Object route(Object input, boolean originalInputIsPublisher) {
FunctionInvocationWrapper function = null;
if (input instanceof Message) {
Message<?> message = (Message<?>) input;
if (this.routingCallback != null) {
FunctionRoutingResult routingResult = this.routingCallback.routingResult(message);
if (routingResult != null) {
if (StringUtils.hasText(routingResult.getFunctionDefinition())) {
function = this.functionFromDefinition(routingResult.getFunctionDefinition());
}
if (routingResult.getMessage() != null) {
message = routingResult.getMessage();
}
}
}
if (function == null) {
if (StringUtils.hasText((String) message.getHeaders().get("spring.cloud.function.definition"))) {
function = functionFromDefinition((String) message.getHeaders().get("spring.cloud.function.definition"));
if (function.isInputTypePublisher()) {
this.assertOriginalInputIsNotPublisher(originalInputIsPublisher);
}
}
else if (StringUtils.hasText((String) message.getHeaders().get("spring.cloud.function.routing-expression"))) {
function = this.functionFromExpression((String) message.getHeaders().get("spring.cloud.function.routing-expression"), message);
if (function.isInputTypePublisher()) {
this.assertOriginalInputIsNotPublisher(originalInputIsPublisher);
}
}
else if (StringUtils.hasText(functionProperties.getRoutingExpression())) {
function = this.functionFromExpression(functionProperties.getRoutingExpression(), message);
}
else if (StringUtils.hasText(functionProperties.getDefinition())) {
function = this.functionFromDefinition(functionProperties.getDefinition());
}
else {
throw new IllegalStateException("Failed to establish route, since neither were provided: "
+ "'spring.cloud.function.definition' as Message header or as application property or "
+ "'spring.cloud.function.routing-expression' as application property. Incoming message: " + input);
}
}
}
else if (input instanceof Publisher) {
if (function == null) {
if (StringUtils.hasText(functionProperties.getDefinition())) {
function = functionFromDefinition(functionProperties.getDefinition());
}
else if (StringUtils.hasText(functionProperties.getRoutingExpression())) {
function = this.functionFromExpression(functionProperties.getRoutingExpression(), input);
}
else {
return input instanceof Mono
? Mono.from((Publisher<?>) input).map(v -> route(v, originalInputIsPublisher))
: Flux.from((Publisher<?>) input).map(v -> route(v, originalInputIsPublisher));
}
}
}
else {
this.assertOriginalInputIsNotPublisher(originalInputIsPublisher);
if (StringUtils.hasText(functionProperties.getRoutingExpression())) {
function = this.functionFromExpression(functionProperties.getRoutingExpression(), input);
}
else
if (StringUtils.hasText(functionProperties.getDefinition())) {
function = functionFromDefinition(functionProperties.getDefinition());
}
else {
throw new IllegalStateException("Failed to establish route, since neither were provided: "
+ "'spring.cloud.function.definition' as Message header or as application property or "
+ "'spring.cloud.function.routing-expression' as application property.");
}
}
return function.apply(input);
}
function = this.functionFromExpression((String) message.getHeaders().get("spring.cloud.function.routing-expression"), message);
org.springframework.cloud.function.context.config.RoutingFunction#functionFromExpression
漏洞就是通过spring.cloud.function.routing-expression
header 的值,解析成 spel 表达式,并且上下文是SpelExpressionParser,然后getValue 被执行了。
修复分析
functionFromExpression增加isViaHeader的参数,用来判断是否是用户传入的 header,如果是的话就使用SimpleEvaluationContext 进行执行。