SpEL表达式注入漏洞详解

程序中如果使用未经校验的输入构造SpEL语句,就有可能造成SpEL表达式注入漏洞,对下游服务可能产生恶意攻击。

在安全角度来看外部来源的数据,均应视为不可信数据,对外部数据,其包含的所有信息都须经过校验或者过滤,再向下游服务进行传递。若无防护手段,攻击者可以通过构造恶意输入,对服务进行攻击。程序中如果使用未经校验的输入构造SpEL语句,就有可能造成SpEL表达式注入漏洞。部分SpEL表达式注入漏洞CVSS3.x 评分极高,nvd认定为高危漏洞,具有高致命性。

一、SpEL表达式介绍

Spring表达式语言(Spring Expression Language,SpEL)是 Spring Framework的核心技术之一,其支持在运行时查询和操作对象图。SpEL语法类似于Unified Expression Language,但提供了更加丰富的功能,最特别的是方法调用与字符串模板功能。

1、SpEL的主要功能

SpEL主要支持以下功能:

  • 文字表达式
  • 布尔和关系运算符
  • 正则表达式
  • 类表达式
  • 访问 properties, arrays, lists, maps
  • 方法调用
  • 关系运算符
  • 参数
  • 调用构造函数
  • Bean引用
  • 构造Array
  • 内嵌lists
  • 内嵌maps
  • 三元运算符
  • 变量
  • 用户定义的函数
  • 集合投影
  • 集合筛选
  • 模板表达式

2、SpEL操作类和方法

SpEL功能强大,可以操作类和方法:

  • 引用方法:dog.run()
  • 引用静态方法:T(java.lang.Math).PI
  • 类实例化:使用new实例化对象,类名必须是全限定名,java.lang包内的除外如Integer、String等
  • 变量定义及赋值引用

3、指定表达式上下文

在解析SpEL之后,获取表达式结果时,可以指定表达式的上下文对象:EvaluationContext

  • StandardEvaluationContext(默认):支持全套SpEL语言和功能配置选项,功能强大但存在隐患
  • SimpleEvaluationContext:仅支持SpEL语法的子集,不包括Java类型引用,构造函数和bean引用,功能相对简单但是安全

二、SpEL表达式注入漏洞

1、部分SpEL注入CVE漏洞

历史报告的大部分SpEL漏洞大多涉及不受信任的用户输入的情况,恶意攻击者可能利用SpEL实现任意代码执行、拒绝服务等攻击,与SpEL相关的部分CVE漏洞见下表:

CVE ID概述评分cvss3.x
CVE-2022-22963在Spring Cloud Function 相关版本,存在SpEL表达式注入。恶意攻击者无需认证可通过构造特定的 HTTP 请求头注入 SpEL 表达式,最终执行任意命令,获取服务器权限。9.8
CVE-2022-22980Spring Data for MongoDB是 Spring Data 项目的一部分,该项目旨在为新的数据存储提供熟悉和一致的基于Spring的编程模型,同时保留存储的特定特征和功能。Spring Data MongoDB应用程序在对包含查询参数占位符的SpEL表达式使用@Query或@Aggregation注解的查询方法进行值绑定时,如果输入未被过滤,则容易受到SpEL注入攻击。9.8
CVE-2018-1273Spring Data Commons, 1.13至1.13.10、2.0至2.0.5之前的版本以及不支持的旧版本包含一个属性绑定器漏洞,该漏洞是由特殊元素的无效化导致的。未经身份验证的远程恶意用户(或攻击者)可以针对Spring Data REST支持的HTTP资源提供特制的请求参数,从而导致远程代码执行攻击。9.8
CVE-2021-45029Groovy代码注入和SpEL注入,导致远程代码执行。此问题影响Apache shenyu 2.4.0和2.4.1。9.8
CVE-2022-22950Spring Framework版本5.3.0 – 5.3.16和较早的不支持版本,用户可以提供可能导致拒绝服务条件的巧尽心思构建的SpEL表达式。6.5
CVE-2016-4977当使用Spring Security OAuth 2.0.0至2.0.9和1.0.0至1.0.5中的白标签视图(whitelabel views)处理授权请求时,response_type参数值作为Spring SpEL执行,这使得恶意用户能够通过创建response_type值来触发远程代码执行。8.8

2、常见的SpEL注入攻击流程

常见的SpEL注入攻击流程如图所示,漏洞的基本条件有: 使用StandardEvaluationContext,2. 未对输入的SpEL进行校验,3. 对表达式调用了getValue()或setValue()方法。当满足上述条件时,就给了攻击者可乘之机。

SpEL表达式注入漏洞详解插图
常见的SpEL注入攻击流程

三、漏洞实例

1、CVE-2022-22963 Spring Cloud Function SpEL注入漏洞

1)基本信息

漏洞IDCVE-2022-22963
漏洞简介在Spring Cloud Function 相关版本,存在SpEL表达式注入。恶意攻击者无需认证可通过构造特定的 HTTP 请求头注入 SpEL 表达式,最终执行任意命令,获取服务器权限。
漏洞发布地址https://nvd.nist.gov/vuln/detail/cve-2022-22963
漏洞安全级别
漏洞代码仓地址https://github.com/spring-cloud/spring-cloud-function
漏洞补丁提交地址https://github.com/spring-cloud/spring-cloud-function/commit/0e89ee27b2e76138c16bcba6f4bca906c4f3744f
漏洞影响包版本3.0.0 <= Spring Cloud Function <= 3.2.2

2)Spring Cloud Function介绍

Spring Cloud Function 是基于 Spring Boot 的函数计算框架。它提供了一个通用的模型,用于在各种平台上部署基于函数的软件,包括像 Amazon AWS Lambda 这样的 FaaS(函数即服务,function as a service)平台。该项目致力于促进函数为主的开发单元,它抽象出所有传输细节和基础架构,并提供一个通用的模型,用于在各种平台上部署基于函数的软件。

3)CVE-2022-22963漏洞攻击路径

使用spring-cloud-function-web的Spring boot 应用,通过设置Message Headers来传达路由指令,也可以在请求头中指定spring.cloud.function.definition或spring.cloud.function.routing-expression作为应用程序属性,允许使用 Spring 表达式语言。

当在application.properties中设置spring.cloud.function.definition=functionRouter从而将默认路由绑定具体函数由用户进行控制。

攻击者调用/functionRouter接口,并在请求头的spring.cloud.function.routing-expression中使用攻击性的SpEL语句,服务端就会解析SpEL并执行。

漏洞攻击图示如图所示:

SpEL表达式注入漏洞详解插图2
CVE-2022-22963漏洞攻击路径

4)CVE-2022-22963漏洞修复方式

该漏洞主要从四处进行了修复:

  • 1)声明一个SimpleEvaluationContext,专用作来自header的SpEL的解析;
  • 2)新增一个布尔变量isViaHeader,用于标记当前Expression是否来自Header;
  • 3)如果是从Header中获取的spring.cloud.function.routing-expression表达式,isViaHeader为true;
  • 4)isViaHeader为true时,expression.getValue指定使用headerEvalContext。

如图所示:

SpEL表达式注入漏洞详解插图4
CVE-2022-22963漏洞修复

2、CVE-2022-22980 Spring Data MongoDB SpEL表达式注入漏洞

1)基本信息

漏洞IDCVE-2022-22980
漏洞简介Spring Data for MongoDB是 Spring Data 项目的一部分,该项目旨在为新的数据存储提供熟悉和一致的基于Spring的编程模型,同时保留存储的特定特征和功能。Spring Data MongoDB应用程序在对包含查询参数占位符的SpEL表达式使用@Query或@Aggregation注解的查询方法进行值绑定时,如果输入未被过滤,则容易受到SpEL注入攻击。
漏洞发布地址https://nvd.nist.gov/vuln/detail/CVE-2022-22980
漏洞安全级别高 (CVSS3.x: 9.8)
漏洞代码仓地址https://github.com/spring-projects/spring-data-mongodb
漏洞补丁提交地址3.3.x https://github.com/spring-projects/spring-data-mongodb/commit/7c5ac764b343d45e5d0abbaba4e82395b471b4c4
3.4.x https://github.com/spring-projects/spring-data-mongodb/commit/5e241c6ea55939c9587fad5058a07d7b3f0ccbd3
漏洞影响包版本Spring Data MongoDB == 3.4.0 3.3.0 <= Spring Data MongoDB <= 3.3.4 其他不维护的老版本
漏洞时间线SpEL表达式注入漏洞详解插图6

2)Spring Data for MongoDB 介绍

Spring Data for MongoDB是Spring Data的一个子模块。 目标是为MongoDB提供一个相近的一致的基于Spring的编程模型。其核心功能是映射POJO到Mongo的DBCollection中的文档,并且提供Repository 风格数据访问层。主要特性有:

  • Spring 配置支持:使用基于 Java 的 @Configuration 类或基于 XML 命名空间的配置来驱动 Mongo 实例和副本
  • MongoTemplate 辅助类:可提高执行常见 Mongo 操作的效率,包括文档和 POJO 之间的集成对象映射
  • 异常处理:异常转换为 Spring 的可移植的数据访问异常层次结构
  • 功能丰富的对象映射与 Spring 的转换服务集成
  • 基于注释的映射元数据、并且可扩展以支持其他元数据格式
  • 持久化和映射生命周期事件
  • 使用 MongoReader/MongoWriter 抽象的低级映射
  • 基于 Java 的查询、条件和更新 DSL
  • Repository 接口的自动实现,包括对自定义查询方法的支持
  • QueryDSL 集成以支持类型安全的查询,以及地理空间整合
  • Map-Reduce 集成
  • JMX 管理和监控
  • 对存储库的 CDI 支持
  • GridFS 支持

3)CVE-2022-22980漏洞攻击路径

SpEL表达式注入漏洞详解插图8
CVE-2022-22980漏洞攻击路径
SpEL表达式注入漏洞详解插图10
CVE-2022-22980漏洞攻击路径

4)CVE-2022-22980复现

  • 1)实验代码:learnjavabug
  • 2)运行服务:com.threedr3am.bug.spring.data.mongodb.Application#main
  • 3)Postman发送请求,如图所示:
SpEL表达式注入漏洞详解插图12
Postman填写参数示例
  • 4)现象:计算器程序被执行

5)CVE-2022-22980修复方式

Spring Data for MongoDB在修复此漏洞时,重新实现evaluator,指定EvaluationContext类型,如图所示:

SpEL表达式注入漏洞详解插图14
CVE-2022-22980修复方式

四、检测与防御手段

  • 1)对于SpEL表达式注入漏洞漏洞,可以使用静态分析工具进行代码检查,可以有效规避部分问题。
  • 2)在此类场景中,对于用户输入,应当仔细校验,检查用户输入的合法性,保障其内容为正常数据。且在端侧与服务侧均应对用户数据进行校验,对非受信用户输入数据进行净化,避免用户输入任意内容。
  • 3)及时更新Spring Framework版本,避免因版本老旧而被利用的问题发生。
  • 4)使用源码静态分析工具进行白盒自动化检测,在代码合入阶段、静态分析监控阶段及时发现相关问题。

发表评论