Spring Cloud Function Spel表达式注入

Spring Cloud Function Spel表达式注入

漏洞概述

Spring Cloud Function 是基于Spring Boot 的函数计算框架(FaaS),支持基于SpEL的函数式动态路由。在特定配置下,3 <= 版本 <= 3.2.2( commit dc5128b 之前)存在SpEL表达式执行导致的RCE。

环境搭建

在IDEA中选择新建项目,然后选择Spring Initializr,输入随机项目名称,然后选择java版本和jdk版本后点击下一步。

image-20220403220315187

选择Spring Web Spring Cloud function

image-20220403222049811

最新版本3.2.2也是存在漏洞的,若在官方出新版本后想要复现此漏洞,那么需要修改pom中spring-cloud-function-web的版本为3.2.2,如下图所示:

image-20220403222337581

确认项目中的spring-cloud-function-web是存在漏洞版本后,就可以直接启动项目了,无需进行任何修改。

漏洞复现

弹计算器payload

POST /functionRouter HTTP/1.1
Host:127.0.0.1:8080
spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("calc")
Content-Type:application/x-www-form-urlencoded
Content-Length: 3

xxx

看一眼POC就知道其实就是简单的在请求的headers头上添加一个spring.cloud.function.routing-expression参数

SpringCloud Function会直接将其参数内容直接带入到SPEL中查询,造成SPEL漏洞注入。

image-20220403231631626

漏洞分析

漏洞是出在SpringCloud Function的RoutingFunction功能上,其功能的目的本身就是为了微服务应运而生的,可以直接通过HTTP请求与单个的函数进行交互,同时为spring.cloud.function.definition参数提供您要调用的函数的名称。

为了更好的分析,可以先在springcloudfunctionspel\src\main\java\com\example\springcloudfunctionspel\SpringcloudfunctionspelApplication.java中写测试Demo

image-20220403232848334

然后再进行访问,请求中写出存在的函数就能够调用

POST /functionRouter HTTP/1.1
Host: localhost:8080
spring.cloud.function.definition: uppercase
Content-Type: text/plain
Content-Length: 3

abc

image-20220403233039490

成功得到abc的大写结果ABC

漏洞存在于header头的spring.cloud.function.routing-expression参数

,和definition相同,他也是官方提供的功能。

在org.springframework.cloud.function.web.util.FunctionWebRequestProcessingHelper#processRequest方法下断点

image-20220405001126121

程序会判断当前请求是否为RoutingFunction

image-20220405001144798

并将我们提交的请求头和请求体内容编译成Message并且传入FunctionInvocationWrapper的apply方法中

image-20220405001504170

跟进RoutingFunction的apply方法

image-20220405001656778

最后进入到org.springframework.cloud.function.context.config.RoutingFunction#route方法中

image-20220405001743831

然后在这里判断了请求headers头中有没有spring.cloud.function.routing-expression参数(这里可以清晰的看到spring.cloud.function.definition也是在这里做判断的)

并将结果带入到this.functionFromExpression()方法中

image-20220405002455553

在这里最后SpelExpressionParser解析了Spel表达式,调用了expression.getValue导致Spel表达式注入

image-20220405003124333

而他的EvaluationContext又采取了默认的StandardEvaluationContext,在不指定EvaluationContext的情况下默认采用的是StandardEvaluationContext,而它包含了SpEL的所有功能,在允许用户控制输入的情况下SpEL表达式是可以操作类及其方法的,可以通过类类型表达式T(Type)或者直接new来调用任意对象的任意方法,成功造成任意命令执行。

image-20220405004040946

补丁分析

  • https://github.com/spring-cloud/spring-cloud-function/commit/dc5128b80c6c04232a081458f637c81a64fa9b52

由于又是Spel注入问题,很容易定位到Context

image-20220330141227267

新增了headerEvalContext常量为SimpleEvaluationContext,显然是为了替换evalContext常量的StandardEvaluationContext而创建的

image-20220403231314162

增加了判断来源是否是header,如果是header就使用属于SimpleEvaluationContext的headerEvalContext,不是header才会使用属于StandardEvaluationContext的evalContext。

从而解决了发送恶意请求就能够RCE的问题。

后记

整个流程也是很清晰,就是官方提供的类似spring.cloud.function.definition的功能,spring.cloud.function.routing-expression有解析Spel表达式的能力,而且使用的是默认的StandardEvaluationContext。最终Spel表达式注入造成了命令执行。

Spring Cloud Gateway rce其实是相似的,都是官方提供的功能有Spel表达式解析能力,但都没有对指定EvaluationContext,采用默认的StandardEvaluationContext从而导致了命令执行。

不过这个影响范围在国内是更小的,后续的回显链挖掘也没有进行(也是因为影响范围吧)

参考

  • https://www.cnblogs.com/wh4am1/p/16062306.html
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot SpEL表达式注入漏洞是一种常见的安全漏洞,攻击者可以利用该漏洞在应用中执行恶意代码,从而导致应用被攻击。下面我将对该漏洞进行分析与复现。 一、漏洞分析 SpringBoot中的SpELSpring Expression Language)是一种基于表达式的语言,用于在运行时动态地计算值或执行逻辑。SpEL表达式可以用于访问对象的属性、调用对象的方法、进行条件判断等操作。在SpringBoot中,SpEL表达式可以用于注解中的属性值、配置文件中的属性值等场景。 在SpEL表达式中,可以使用一些特殊的语法来引用Bean对象或调用Bean对象的方法。例如,可以使用`#{beanName.methodName()}`的语法来调用Bean对象的方法。如果在SpEL表达式中使用了未经过滤的用户输入,就会存在SpEL表达式注入漏洞。 攻击者可以通过构造恶意的SpEL表达式,将其注入到应用中,从而执行恶意代码。例如,可以将`#{T(java.lang.Runtime).getRuntime().exec('calc')}`注入到应用中,从而在受害者机器上执行计算器程序。 二、漏洞复现 下面我将通过一个简单的漏洞复现来说明SpEL表达式注入漏洞的危害性。 1. 创建一个SpringBoot应用 首先,我们需要创建一个SpringBoot应用。可以使用Spring Initializr来快速创建一个基本的SpringBoot应用。 2. 添加注解 在创建好的SpringBoot应用中,我们可以添加一个Controller类,并在其中添加一个RequestMapping注解。在RequestMapping注解中,我们可以使用SpEL表达式来引用Bean对象或调用Bean对象的方法。 ```java @RestController public class MyController { @RequestMapping("/test") public String test() { return "hello world"; } @RequestMapping(value = "/{name}", method = RequestMethod.GET) public String sayHello(@PathVariable("name") String name) { return "Hello " + name + "!"; } @RequestMapping(value = "/spel", method = RequestMethod.GET) public String spel() { String expression = "#{T(java.lang.Runtime).getRuntime().exec('calc')}"; ExpressionParser parser = new SpelExpressionParser(); Expression exp = parser.parseExpression(expression); return exp.getValue().toString(); } } ``` 在上述代码中,我们在/spel接口中使用了SpEL表达式来调用Runtime.getRuntime().exec方法,从而执行计算器程序。 3. 启动应用 启动应用后,访问/spel接口,可以看到计算器程序被成功执行。 4. 防范措施 为了防范SpEL表达式注入漏洞,我们可以采取以下措施: 1. 对用户输入进行过滤和验证,避免未经过滤的用户输入被注入SpEL表达式中。 2. 尽量避免在注解或配置文件中使用SpEL表达式。 3. 对于必须使用SpEL表达式的场景,可以对SpEL表达式进行白名单过滤,只允许特定的SpEL表达式被执行。 4. 在应用中禁用动态表达式功能,避免SpEL表达式被执行。 5. 总结 SpEL表达式注入漏洞是一种常见的安全漏洞,攻击者可以利用该漏洞在应用中执行恶意代码。为了防范该漏洞,我们需要对用户输入进行过滤和验证,避免未经过滤的用户输入被注入SpEL表达式中。同时,尽量避免在注解或配置文件中使用SpEL表达式,对于必须使用SpEL表达式的场景,可以对SpEL表达式进行白名单过滤,只允许特定的SpEL表达式被执行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值