【摘要】 程序中如果使用未经校验的输入构造 SpEL 语句,就有可能造成 SpEL 表达式注入漏洞,对下游服务可能产生恶意gongji(attack)。本文介绍了 SpEL 表达式以及常见的 SpEL 注入gongji(attack),详细地介绍了部分漏洞gongji(attack)实例以及常用的漏洞检测与防御手段。
在安全角度来看外部来源的数据,均应视为不可信数据,对外部数据,其包含的所有信息都须经过校验或者过滤,再向下游服务进行传递。若无防护手段,gongji(attack)者可以通过构造恶意输入,对服务进行gongji(attack)。程序中如果使用未经校验的输入构造 SpEL 语句,就有可能造成 SpEL 表达式注入漏洞。部分 SpEL 表达式注入漏洞 CVSS3.x 评分极高,nvd 认定为高危漏洞,具有高致命性。
1 SpEL 表达式介绍
Spring 表达式语言(Spring Expression Language,SpEL)是 Spring Framework 的核心技术之一,其支持在运行时查询和操作对象图。SpEL 语法类似于 Unified Expression Language,但提供了更加丰富的功能,最特别的是方法调用与字符串模板功能。SpEL 主要支持以下功能:
文字表达式
布尔和关系运算符
正则表达式
类表达式
访问 properties, arrays, lists, maps
方法调用
关系运算符
参数
调用构造函数
Bean 引用
构造 Array
内嵌 lists
内嵌 maps
三元运算符
变量
用户定义的函数
集合投影
集合筛选
模板表达式
SpEL 功能强大,可以操作类和方法。
引用方法:dog.run()
引用静态方法:T(java.lang.Math).PI
类实例化:使用 new 实例化对象,类名必须是全限定名,java.lang 包内的除外如 Integer、String 等
变量定义及赋值引用
在解析 SpEL 之后,获取表达式结果时,可以指定表达式的上下文对象:EvaluationContext
(默认)StandardEvaluationContext:支持全套 SpEL 语言和功能配置选项,功能强大但存在隐患
SimpleEvaluationContext:仅支持 SpEL 语法的子集,不包括 Java 类型引用,构造函数和 bean 引用,功能相对简单但是安全
2 SpEL 表达式注入漏洞
历史报告的大部分 SpEL 漏洞大多涉及不受信任的用户输入的情况,恶意gongji(attack)者可能利用 SpEL 实现任意代码执行、拒绝服务等gongji(attack),与 SpEL 相关的部分 CVE 漏洞见表 1。
表 1 部分 SpEL 注入 CVE 漏洞
CVE ID | 概述 | 评分 cvss3.x |
CVE-2022-22963 | 在 Spring Cloud Function 相关版本,存在 SpEL 表达式注入。恶意gongji(attack)者无需认证可通过构造特定的 HTTP 请求头注入 SpEL 表达式,最终执行任意命令,获取服务器权限。 | 9.8 |
CVE-2022-22980 | Spring Data for MongoDB 是 Spring Data 项目的一部分,该项目旨在为新的数据存储提供熟悉和一致的基于 Spring 的编程模型,同时保留存储的特定特征和功能。Spring Data MongoDB 应用程序在对包含查询参数占位符的 SpEL 表达式使用 @Query 或 @Aggregation 注解的查询方法进行值绑定时,如果输入未被过滤,则容易受到 SpEL 注入gongji(attack)。 | 9.8 |
CVE-2018-1273 | Spring Data Commons, 1.13 至 1.13.10、2.0 至 2.0.5 之前的版本以及不支持的旧版本包含一个属性绑定器漏洞,该漏洞是由特殊元素的无效化导致的。未经身份验证的远程恶意用户(或gongji(attack)者)可以针对 Spring Data REST 支持的 HTTP 资源提供特制的请求参数,从而导致远程代码执行gongji(attack)。 | 9.8 |
CVE-2021-45029 | Groovy 代码注入和 SpEL 注入,导致远程代码执行。此问题影响 Apache shenyu 2.4.0 和 2.4.1。 | 9.8 |
CVE-2022-22950 | Spring 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 |
常见的 SpEL 注入gongji(attack)流程如图 1 所示,漏洞的基本条件有: 使用 StandardEvaluationContext,2. 未对输入的 SpEL 进行校验,3. 对表达式调用了 getValue () 或 setValue () 方法。当满足上述条件时,就给了gongji(attack)者可乘之机。
图 1 常见的 SpEL 注入gongji(attack)流程
3 漏洞实例
3.1 CVE-2022-22963 Spring Cloud Function SpEL 注入漏洞
3.1.1 基本信息
漏洞 id | CVE-2022-22963 |
漏洞简介 | 在 Spring Cloud Function 相关版本,存在 SpEL 表达式注入。恶意gongji(attack)者无需认证可通过构造特定的 HTTP 请求头注入 SpEL 表达式,最终执行任意命令,获取服务器权限。 |
漏洞发布地址 | |
漏洞安全级别 | 高 |
漏洞代码仓地址 | |
漏洞补丁提交地址 | |
漏洞影响包版本 | 3.0.0 <= Spring Cloud Function <= 3.2.2 |
3.1.2 Spring Cloud Function 介绍
Spring Cloud Function 是基于 Spring Boot 的函数计算框架。它提供了一个通用的模型,用于在各种平台上部署基于函数的软件,包括像 Amazon AWS Lambda 这样的 FaaS(函数即服务,function as a service)平台。该项目致力于促进函数为主的开发单元,它抽象出所有传输细节和基础架构,并提供一个通用的模型,用于在各种平台上部署基于函数的软件。
3.1.3 CVE-2022-22963 漏洞gongji(attack)路径
使用 spring-cloud-function-web 的 Spring boot 应用,通过设置 Message Headers 来传达路由指令,也可以在请求头中指定 spring.cloud.function.definition 或 spring.cloud.function.routing-expression 作为应用程序属性,允许使用 Spring 表达式语言。
当在 application.properties 中设置 spring.cloud.function.definitinotallow=functionRouter 从而将默认路由绑定具体函数由用户进行控制。
gongji(attack)者调用 /functionRouter 接口,并在请求头的 spring.cloud.function.routing-expression 中使用gongji(attack)性的 SpEL 语句,服务端就会解析 SpEL 并执行。
漏洞gongji(attack)图示如图 2 所示。
图 2 CVE-2022-22963 漏洞gongji(attack)路径
3.1.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。如图 3 所示。
图 3 CVE-2022-22963 漏洞修复
3.2 CVE-2022-22980 Spring Data MongoDB SpEL 表达式注入漏洞
3.2.1 基本信息
漏洞 id | CVE-2022-22980 |
漏洞简介 | Spring Data for MongoDB 是 Spring Data 项目的一部分,该项目旨在为新的数据存储提供熟悉和一致的基于 Spring 的编程模型,同时保留存储的特定特征和功能。Spring Data MongoDB 应用程序在对包含查询参数占位符的 SpEL 表达式使用 @Query 或 @Aggregation 注解的查询方法进行值绑定时,如果输入未被过滤,则容易受到 SpEL 注入攻击。 |
漏洞发布地址 | |
漏洞安全级别 | 高 (CVSS3.x: 9.8) |
漏洞代码仓地址 | |
漏洞补丁提交地址 | 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 其他不维护的老版本 |
漏洞时间线 |
3.2.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.2.3 CVE-2022-22980 漏洞gongji(attack)路径
图 4 CVE-2022-22980 漏洞gongji(attack)路径
3.2.4 CVE-2022-22980 复现
1) 实验代码:learnjavabug
2) 运行服务,com.threedr3am.bug.spring.data.mongodb.Application#main
3) Postman 发送请求,如图 5 所示
图 5 Postman 填写参数示例
4) 现象:计算器程序被执行
3.2.5 CVE-2022-22980 修复方式
Spring Data for MongoDB 在修复此漏洞时,重新实现 evaluator,指定 EvaluationContext 类型,如图 6 所示。
图 6 CVE-2022-22980 修复方式
4 检测与防御手段
(1)对于 SpEL 表达式注入漏洞漏洞,可以使用静态分析工具进行代码检查,可以有效规避部分问题。
(2)在此类场景中,对于用户输入,应当仔细校验,检查用户输入的合法性,保障其内容为正常数据。且在端侧与服务侧均应对用户数据进行校验,对非受信用户输入数据进行净化,避免用户输入任意内容。
(3)及时更新 Spring Framework 版本,避免因版本老旧而被利用的问题发生。
(4)使用源码静态分析工具进行白盒自动化检测,在代码合入阶段、静态分析监控阶段及时发现相关问题。
文章来自 PaaS 技术创新 Lab,PaaS 技术创新 Lab 隶属于华为云,致力于综合利用软件分析、数据挖掘、机器学习等技术,为软件研发人员提供下一代智能研发工具服务的核心引擎和智慧大脑。我们将聚焦软件工程领域硬核能力,不断构筑研发利器,持续交付高价值商业特性!加入我们,一起开创研发新 “境界”!