简单了解
SpEL(Spring Expression Language) 是 Spring 中的表达式语言,用于在运行时评估和处理表达式。它提供了一种灵活的方式来访问和操作对象的属性、方法和其他表达式。SpEL可以用于配置文件、注解、XML 配置等多种场景,用于实现动态的、可配置的行为。它支持常见的表达式操作,如算术运算、逻辑运算、条件判断、集合操作等,并且可以与 Spring 框架的其他功能整合使用。
由于SpEL具有代码调用,我们可以通过SpEL注入来执行系统命令,进而导致RCE漏洞
SpEL格式
SpEL有多种格式
#{expression}
这是 SpEL 最常见的格式。在 XML 配置文件中,可以使用 #{}
包裹表达式来引用 SpEL 表达式。例如:
java"><property name="name" value="#{person.name}" />
${expression}
种格式通常用于读取属性文件中的值,并支持占位符的替换。在属性文件中,可以使用 ${}
包裹表达式来引用 SpEL 表达式。例如:
java"><property name="name" value="${app.name}" />
或者
java">package com.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;@Configuration
@PropertySource("classpath:jdbc.properties")
public class AppConfig {@Value("${jdbc.url}")String url;@Value("${jdbc.user}")String username;@Value("${jdbc.pwd}")String password;@Value("${jdbc.driver}")String driverClassName;public void print(){System.out.println("url = " + url);System.out.println("username = " + username);System.out.println("password = " + password);System.out.println("driverClassName = " + driverClassName);}}
@annotation
在 Spring 注解中,可以使用 @
符号引用 SpEL 表达式。例如,在 @Scheduled
注解中使用 SpEL 表达式来指定调度的时间:
java">@Scheduled(cron = "#{systemProperties['scheduler.cron.expression']}")
SpelExpressionParser
通过使用 SpelExpressionParser
类,可以在 Java 代码中直接解析 SpEL 表达式。例如:
java">@RestController
public class demo {@RequestMapping("/demo1")public Object demo(String poc){System.out.println(poc);// 创建 SpEL 表达式解析器ExpressionParser parser = new SpelExpressionParser();// 解析 SpEL 表达式,将字符串 poc 解析为一个可执行的 SpEL 表达式对象Expression exp = parser.parseExpression(poc);// 使用表达式对象获取表达式的值return exp.getValue();}
}
当我们传入?poc=1+1
时,并不能解析,应该是url编码的问题,首先将1+1
进行url编码一下,就是?poc=1%2B1
此时界面会返回2
如何利用SpEL来执行命令?
这个表达式解析和其他语言的eval
函数有点类型,但是不一样,并不是直接传入poc=Runtime.getRuntime().exec("whoami")
就可以执行命令了,还需要进行其他处理。
类类型表达式
通过类类型表达式,可以访问类静态方法以及字段,主要是通过T()操作符
我们可以通过T操作符获取某一个类的静态方法,然后再通过表达式解析,具体使用格式:T(类的权限命名).方法名(参数值)
比如
java">T(java.lang.Runtime).getRuntime.exec("calc")
类类型表达式的局限性
T操作符只能调用静态公共方法,并不是所有的方法都能调用。
SpelExpressionParser的局限性
在SpelExpressionParser的局限性存在SimpleEvaluationContext
和StandardEvaluationContext
两种上下文环境,这两种上下文环境中对命令执行有着比较重要的影响
SimpleEvaluationContext
不支持类类型表达式,不能进行命令执行StandardEvaluationContext
支持类型型表达式,可以进行命令执行
默认情况下,在不指定上下文环境下,默认为StandardEvaluationContext
相关笔记代码已上传至Git仓库:JavaCodeAudit