戳上面的蓝字关注我们哦!
01 漏洞概述
—
今早看到绿盟发的一条关于Spring Cloud的Function组件存在SPEL表达式漏洞,就借此机会深入分析一下Function组件漏洞的形成过程,从官网上看到的内容发现这是一个从请求头注入进SPEL表达式的RCE漏洞。
“由于Spring Cloud Function中RoutingFunction类的apply方法将请求头中的“spring.cloud.function.routing-expression”参数作为Spel表达式进行处理,造成了Spel表达式注入漏洞,攻击者可利用该漏洞远程执行任意代码。”
02 影响范围
—
3.0.0.RELEASE <= Spring Cloud Function <= 3.2.2
03 漏洞复现
—
在漏洞官网GitHub上给出了修复commit
可以看到官网给出的poc代码如下:
就是在请求的headers头上添加一个spring.cloud.function.routing-expression参数
SpringCloud Function会直接将其参数内容直接带入到SPEL中查询,造成SPEL漏洞注入。
这里我用https://github.com/jwwam/scfunc项目简单的搭建环境
该项目是用的2.0.2版本,不在影响范围内,因此还要修改pom.xml文件内容:
`<?xml version="1.0" encoding="UTF-8"?>``<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"` `xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">` `<modelVersion>4.0.0</modelVersion>` `<parent>` `<groupId>org.springframework.boot</groupId>` `<artifactId>spring-boot-starter-parent</artifactId>` `<version>2.5.5</version>` `<relativePath/> <!-- lookup parent from repository -->` `</parent>` `<groupId>com.zyq</groupId>` `<artifactId>scfunc</artifactId>` `<version>0.0.1-SNAPSHOT</version>` `<name>scfunc</name>` `<description>Demo project for Spring Boot</description>`` ` `<properties>` `<java.version>1.8</java.version>` `<spring-cloud.version>Greenwich.SR2</spring-cloud.version>` `</properties>`` ` `<dependencies>` `<dependency>` `<groupId>org.springframework.boot</groupId>` `<artifactId>spring-boot-starter</artifactId>` `</dependency>` `<dependency>` `<groupId>org.springframework.cloud</groupId>` `<artifactId>spring-cloud-function-context</artifactId>` `<version>3.1.4</version>` `</dependency>`` ` `<dependency>` `<groupId>org.springframework.boot</groupId>` `<artifactId>spring-boot-starter-test</artifactId>` `<scope>test</scope>` `</dependency>` `<dependency>` `<groupId>org.springframework.cloud</groupId>` `<artifactId>spring-cloud-starter-function-web</artifactId>` `<version>3.1.4</version>` `</dependency>` `<dependency>` `<groupId>org.projectlombok</groupId>` `<artifactId>lombok</artifactId>` `<optional>true</optional>` `</dependency>`` ` `</dependencies>`` ` `<build>` `<plugins>` `<plugin>` `<groupId>org.apache.maven.plugins</groupId>` `<artifactId>maven-deploy-plugin</artifactId>` `<configuration>` `<skip>true</skip>` `</configuration>` `</plugin>` `</plugins>` `</build>`` ``</project>`
这里构造恶意请求访问RoutingFunction功能
04 漏洞原理分析
—
漏洞是出在SpringCloud Function的RoutingFunction功能上,其功能的目的本身就是为了微服务应运而生的,可以直接通过HTTP请求与单个的函数进行交互,同时为spring.cloud.function.definition参数提供您要调用的函数的名称。
拿之前的scfunc项目举个例子
我有一个反转字符串的函数,我如果想调用它,我可以通过如下请求来访问
`POST /functionRouter HTTP/1.1``Host: localhost:8080``spring.cloud.function.definition: reverseString``Content-Type: text/plain``Content-Length: 3`` ``abc`
其结果就会在页面上输出cba,因此我们只需要在header头上指定要调用的函数名称就可以对其进行调用。
接下来就系好安全带,准备开始正文分析了
根据上述所说,漏洞是存在于header头的spring.cloud.function.routing-expression参数
我们就开始从SpringCloud Function的Controller处理来一步步往下跟入。
在org.springframework.cloud.function.web.mvc.FunctionController#post方法上下断点
程序会获取body中的参数,并传入processRequest方法中
程序会判断当前请求是否为RoutingFunction,并将请求的内容和Header头编译成Message带入到FunctionInvocationWrapper.apply方法中,随后又进入其中的doApply方法
跟进RoutingFunction的apply方法
最后进入到org.springframework.cloud.function.context.config.RoutingFunction#route方法中
在这里判断了请求headers头中有没有spring.cloud.function.routing-expression参数
并将结果带入到this.functionFromExpression()方法中
最终直接由SpelExpressionParser来解析,导致Spel表达式注入。
05 修复方案
—
其中的this.headerEvalContext变量就是由SimpleEvaluationContext来解析的。
06 Reference
—
[1].http://blog.nsfocus.net/spring-cloud-function-spel/
[4].https://blog.csdn.net/zhulier1124/article/details/100133932