尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

EL注入漏洞原理与防御实战指南

EL注入漏洞原理与防御实战指南 1. 表达式语言注入基础概念表达式语言Expression Language简称EL是Java EE规范中用于简化JSP页面数据访问的脚本语言。它允许开发者通过简单的语法在JSP页面中直接访问JavaBean属性、集合元素和隐式对象。典型的EL表达式形如${user.name}这种设计初衷是为了取代JSP脚本片段Scriptlet使视图层代码更加简洁。然而当EL表达式可以被外部用户控制时就会产生EL注入漏洞。攻击者通过精心构造的输入参数将恶意EL表达式注入到服务器端执行环境中。与SQL注入类似这种攻击利用了应用程序对用户输入缺乏充分验证的缺陷。关键区别EL注入发生在视图渲染阶段而SQL注入发生在数据访问层。前者可能导致任意代码执行后者则危害数据库安全。2. EL注入漏洞产生原理2.1 JSP处理流程中的风险点当JSP页面包含${expression}语法时容器会通过以下步骤处理页面编译阶段将EL表达式转换为Java代码请求处理阶段通过ValueExpression解析表达式渲染输出阶段执行表达式并替换为结果值漏洞常出现在以下场景直接使用${param.input}渲染未过滤的用户输入通过c:out标签但未设置escapeXml属性使用JSTL但允许表达式包含动态内容2.2 危险表达式示例攻击者可能注入的恶意表达式包括${pageContext.request.getSession().setAttribute(admin,true)} ${Runtime.getRuntime().exec(rm -rf /)} ${.getClass().forName(java.lang.Runtime)}这些表达式可以修改应用运行状态执行系统命令通过反射访问敏感API3. 实战漏洞检测方法3.1 基础检测流程输入点定位查找所有接收用户输入的参数GET/POST/Header/Cookie特别关注回显到页面的参数基础探测GET /page.jsp?input${12} HTTP/1.1观察返回页面是否显示3环境检测${pageContext.request.serverName} ${header[user-agent]}这些表达式可以泄露服务器信息3.2 进阶利用技巧命令执行检测${.getClass().forName(java.lang.Runtime).getMethod(exec,.getClass()).invoke(.getClass().forName(java.lang.Runtime).getMethod(getRuntime).invoke(null),calc.exe)}这个复杂的反射调用可以绕过简单过滤文件操作检测${Files.list(Paths.get(/)).toArray()}列出服务器根目录文件内存马注入 通过EL表达式注册Filter/Servlet实现持久化控制4. 防御方案深度解析4.1 输入验证策略白名单过滤public static String sanitizeEL(String input) { if(!input.matches([a-zA-Z0-9_\\-])) { throw new IllegalArgumentException(Invalid input); } return input; }上下文输出编码c:out value${param.userInput} escapeXmltrue/4.2 容器级防护禁用EL表达式jsp-config jsp-property-group url-pattern*.jsp/url-pattern el-ignoredtrue/el-ignored /jsp-property-group /jsp-config使用安全框架OWASP ESAPISpring Security Taglibs4.3 运行时防护自定义ELResolverpublic class SafeELResolver extends ELResolver { Override public Object getValue(ELContext context, Object base, Object property) { if(property.toString().contains(Runtime)) { throw new PropertyNotFoundException(Access denied); } return null; } }SecurityManager配置Policy.setPolicy(new RestrictivePolicy()); System.setSecurityManager(new SecurityManager());5. 典型漏洞案例分析5.1 案例1模板引擎误配置某CMS系统错误配置public String renderTemplate(String template) { ExpressionFactory factory ExpressionFactory.newInstance(); ValueExpression ve factory.createValueExpression(new ELContext() {...}, template, String.class); return (String) ve.getValue(context); }攻击者可以传入${恶意表达式}作为template参数5.2 案例2JSP自定义标签缺陷缺陷标签实现public void doTag() throws JspException { String value getAttributes().get(value); getJspContext().getOut().print(value); }未对value属性进行EL表达式过滤6. 自动化检测工具Burp Suite插件ELInjectorELScanner专用扫描器java -jar elscan.jar -u http://target.com -d wordlist.txt代码审计工具FindSecBugsSonarQube EL规则7. 开发安全实践安全编码规范禁止直接输出未过滤的request参数所有动态内容必须经过编码代码审查要点检查所有.getParameter()调用验证JSTL标签使用方式审计自定义标签实现测试用例设计Test public void testELInjection() { String payload ${11}; String result testPage(payload); assertFalse(result.contains(2)); }8. 高级利用技术8.1 表达式绕过技巧字符串拼接${[class].forName(java.lang.Runtime)}反射链构造${request.getClass().getMethod(getHeader,.getClass()).invoke(request,user-agent)}属性访问替代${pageContext.getRequest().getSession().setAttribute(admin,true)}8.2 内存驻留技术通过EL表达式注册恶意Filter${pageContext.servletContext.addFilter(evil, [class].forName(metasploit.Payload)).newInstance()}9. 修复方案对比方案类型实施难度防护效果性能影响输入过滤低中可忽略输出编码中高轻微禁用EL高完全无安全框架中高中等10. 企业级防护架构WAF规则示例location ~* \.jsp$ { set $block_el 0; if ($args ~* \$\{ ) { set $block_el 1; } if ($block_el 1) { return 403; } }RASP防护public class ELInjectionHook implements RASPHook { public void check(Method method, Object[] args) { if(method.getName().equals(evaluate) args[0].toString().contains(Runtime)) { throw new SecurityException(EL injection detected); } } }在实际企业环境中建议采用分层防御策略开发阶段静态代码扫描安全培训测试阶段DAST扫描人工渗透运行阶段WAFRASP防护监控阶段日志分析异常检测对于历史遗留系统可优先采用容器级防护措施如配置Tomcat的JspServlet初始化参数禁用EL表达式。新系统则应从设计阶段就考虑使用现代模板引擎如Thymeleaf替代JSP。
返回列表