1. 表达式语言注入基础认知
第一次听说"表达式语言注入"这个概念时,我正为一个电商项目调试用户评价模块。当时发现前端输入的${1+1}在服务端渲染后神奇地变成了2,这个偶然发现让我意识到表达式解析可能成为攻击入口。表达式语言(Expression Language,简称EL)最初作为JSP 2.0标准组件出现,主要简化JSP页面中的数据访问逻辑。它的核心特征是能在运行时动态解析字符串表达式,比如${user.name}会自动替换为当前用户的姓名属性。
现代EL实现已不限于JSP环境,Spring表达式语言(SpEL)、OGNL、Unified EL等变种广泛应用于模板引擎(如Thymeleaf)、配置系统(如Spring Security)和规则引擎中。这种动态求值特性在带来便利的同时,也引入了安全风险——当用户可控输入未经处理直接拼接到EL表达式时,攻击者就能注入恶意表达式实现任意代码执行。去年某央企OA系统的数据泄露事件,根本原因就是工作流引擎的审批意见字段存在EL注入漏洞。
与SQL注入不同,EL注入直接发生在应用逻辑层。攻击者通过精心构造的表达式可以:
- 访问服务器内存中的任意对象(包括敏感配置)
- 调用Java类静态方法(如Runtime.exec())
- 操作文件系统和数据库连接
- 进行反射调用突破沙箱限制
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. EL注入漏洞原理深度剖析
2.1 典型漏洞触发场景
通过审计真实案例,我总结出三类高危场景:
模板引擎动态渲染
java复制// Thymeleaf危险示例
@GetMapping("/profile")
public String profile(@RequestParam String username, Model model) {
model.addAttribute("welcomeMsg", "Hello " + username);
return "userProfile";
}
当username为${T(java.lang.Runtime).getRuntime().exec('calc')}时,Thymeleaf解析模板会执行系统命令。
Spring表达式动态解析
java复制// SpEL解析漏洞
@GetMapping("/search")
public String search(@RequestParam String filter) {
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext();
// 危险操作:直接解析用户输入
parser.parseExpression(filter).getValue(context);
}
JSP隐式EL求值
jsp复制<!-- 存在漏洞的JSP代码 -->
<c:out value="${param.searchKeyword}" />
即使使用JSTL标签,若web.xml未配置<el-ignored>true</el-ignored>,攻击者仍可通过URL传入${maliciousCode}触发漏洞。
2.2 表达式解析过程分析
以Spring SpEL为例,表达式解析分为三个阶段:
