1. 表达式语言(EL)基础概念解析
表达式语言(Expression Language)是JSP 2.0引入的核心特性之一,它提供了一种在JSP页面中简化Java代码编写的机制。EL最初设计目的是替代JSP页面中的脚本表达式(<%= %>)和JavaBean访问代码,使页面更简洁、更易维护。
EL语法采用${expression}的形式,其中expression可以是变量、运算符、函数调用等组合。例如${user.name}表示获取user对象的name属性值。这种简洁的语法让非Java开发人员也能快速上手页面开发。
关键特性:EL支持自动类型转换、空值处理(null不会抛出NullPointerException)、运算符重载等实用功能,这些特性大大降低了JSP开发中的常见错误。
2. EL注入漏洞原理剖析
2.1 什么是EL注入
EL注入(Expression Language Injection)是指攻击者能够控制EL表达式的输入,导致服务器执行恶意EL表达式的一种安全漏洞。这种漏洞通常出现在以下场景:
- 用户输入直接拼接到EL表达式中
- 框架配置不当允许执行动态EL
- 反序列化过程中未对EL表达式进行过滤
2.2 漏洞产生条件
EL注入需要同时满足三个条件:
- 应用使用EL表达式
- 用户输入能够影响EL表达式内容
- 目标环境使用支持功能强大的EL实现(如Spring EL)
典型的漏洞代码示例:
java复制// 危险代码 - 用户输入直接拼接
String userInput = request.getParameter("input");
String elExpression = "${" + userInput + "}";
// 后续代码执行该EL表达式
2.3 攻击危害分析
成功的EL注入可能导致:
- 任意代码执行(最严重情况)
- 敏感信息泄露
- 服务器文件系统访问
- 拒绝服务攻击
- 服务器端请求伪造(SSRF)
3. EL注入实战演示
3.1 基础测试环境搭建
我们使用Spring Boot创建一个简单的演示应用:
- 添加依赖:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 创建有漏洞的Controller:
java复制@RestController
public class VulnerableController {
@GetMapping("/eval")
public String evaluate(@RequestParam String expression) {
ExpressionParser parser = new SpelExpressionParser();
return parser.parseExpression(expression).getValue().toString();
}
}
3.2 常见攻击载荷示例
3.2.1 基本信息泄露
code复制${7*7} // 返回49,确认EL执行
${T(java.lang.System).getProperties()} // 获取系统属性
3.2.2 文件系统访问
code复制${T(java.lang.Runtime).getRuntime().exec('cat /etc/passwd')}
3.2.3 远程代码执行
code复制${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('whoami').getInputStream())}
3.3 漏洞检测方法
- 简单探测:输入${1+2}等简单表达式,观察是否返回计算结果
- 上下文识别:判断使用的是标准JSP EL还是Spring EL
- 沙箱检测:尝试访问受限类和方法,评估执行环境限制
4. 防御措施与最佳实践
4.1 输入验证与过滤
对所有可能进入EL表达式的用户输入进行严格验证:
java复制// 白名单验证示例
if (!expression.matches("[a-zA-Z0-9_\\-\\.]+")) {
throw new IllegalArgumentException("Invalid expression");
}
4.2 安全配置
对于Spring框架:
java复制@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.expressionHandler(new DefaultEvaluationContext());
}
}
4.3 其他防护措施
- 使用安全的EL解析器配置:
java复制SpelParserConfiguration config = new SpelParserConfiguration(
SpelCompilerMode.OFF,
getClass().getClassLoader());
ExpressionParser parser = new SpelExpressionParser(config);
-
最小权限原则:运行应用的账户应具有最小必要权限
-
定期安全扫描:使用OWASP ZAP等工具定期检测EL注入漏洞
5. 实际案例分析
5.1 Spring框架历史漏洞
CVE-2018-1270:Spring Messaging组件中的EL注入漏洞,允许攻击者通过特制的消息导致远程代码执行。
漏洞修复方式:
- 升级到Spring Framework 5.0.5或更高版本
- 禁用不必要的表达式解析功能
5.2 JSP自定义标签漏洞
某些自定义JSP标签库未正确过滤用户输入,导致EL注入。例如:
jsp复制<my:tag value="${param.userInput}"/>
修复方案:
- 对标签属性值进行HTML编码
- 避免直接使用用户输入构建EL表达式
6. 高级研究与检测工具
6.1 静态分析工具
- FindSecBugs:检测Java代码中的EL注入模式
- SonarQube:配置自定义规则检测不安全的EL使用
6.2 动态测试工具
- Burp Suite:使用Intruder模块自动化测试EL注入
- OWASP ZAP:使用主动扫描规则检测EL注入
6.3 沙箱逃逸技术
在某些受限环境中,攻击者可能尝试绕过EL限制:
- 使用反射访问受限类
- 通过类加载器机制加载外部代码
- 利用类型转换特性绕过检查
防御建议:
- 完全禁用表达式功能(如无必要)
- 实现严格的类/方法访问控制
- 监控异常的类加载行为
