OGNL注入入门(未完 占坑

参考:
https://www.cnblogs.com/LittleHann/p/17788847.html

OGNL表达式:
因为OGNL表达式是Struts2的默认表达式语言,所以只针对Struts2标签有效;然而EL在HTML中也可以使用。

Struts2标签用的都是OGNL表达式语言,所以它多数都是去值栈的栈顶找值,找不到再去作用域;相反,EL都是去Map集合作用域中找。

  • 支持对象方法调用,如objName.methodName()
  • 支持类静态方法调用和值访问,表达式的格式为 @[类全名(包括包路径)]@[方法名|值名],如@java.lang.String@format(‘fruit%s’,’frt’)
  • 支持赋值操作和表达式串联,如price=100、discount=0.8,calculatePrice(price*discount)这个表达式会返回80
  • 访问OGNL上下文(OGNL context)和ActionContext
  • 操作集合对象
  • 可以直接new一个对象

0x1: 表达式(expression)语法

OGNL支持各种纷繁复杂的表达式。但是最最基本的表达式的原型,是将对象的引用值用点串联起来,从左到右,每一次表达式计算返回的结果成为当前对象,后面部分接着在当前对象上进行计算,一直到全部表达式计算完成,返回最后得到的对象。

OGNL则针对这条基本原则进行不断的扩充,从而使之支持对象树、数组、容器的访问,甚至是类似SQL中的投影选择等操作。

1)通过.获取对象的属性或方法

student
student.name
student.school
student.school.name
student.takingClasses("英语")

2)三种类型对象的获取

静态对象、静态方法和静态变量:@

  • @java.lang.System@getProperty("user.dir")
  • @java.lang.Math@abs(-111)

非原生类型对象:#

  • #student.name
  • #student.takingClasses("英语")

简单对象:直接获取

  • "string".lenth
  • 5
  • true

%符号的用途是在标志的属性为字符串类型时,告诉执行环境%{}里的是OGNL表达式并计算表达式的值。

$在配置文件中引用OGNL表达式。

3)集合表达式

new创建实例:

new java.lang.String("testnew")

{}和[]的用法:在OGNL中,可以用{}或者它的组合来创建列表、数组和map,[]可以获取下标元素。

创建list:{value1,value2...}

{1,3,5}[1]

创建数组:new type[]{value1,value2...}

new int[]{1,3,5}[0]

创建map:#{key:value,key1:value1...}

#{"name":"xiaoming","school":"tsinghua"}["school"]

页面取值区别如下表:

名称 servlet OGNL EL
parameters request.getParameter(“username”) #username ${username}
request request.getAttribute(“userName”) #request.userName ${requestScope.username}
session session.getAttribute(“userName”) #session.userName ${sessionScope.username}
application application.getAttribute(“userName”) #application.userName ${applicationScope.username}
attr 用于按request > session > application顺序访问其属性(attribute) #attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止

0x2:Struts OGNL注入漏洞

webwork2和现在的Struts2.x中使用OGNL取代原来的EL来做界面数据绑定,所谓界面数据绑定,也就是把界面元素(例如一个textfield,hidden)和对象层某个类的某个属性绑定在一起,修改和显示自动同步。而Struts2框架正是因为滥用OGNL表达式,使之成为了“漏洞之王”。

0x3:Mybatis SQL解析OGNL注入漏洞

Mybatis在动态SQL中,可以解析OGNL表达式,如果我们控制了一个变量,并且该变量可以被解析成OGNL表达式,就能够实现OGNL表达式注入。

在OGNL>=3.1.25 3.1.12版本设置了黑名单:

public static Object invokeMethod(Object target, Method method, Object[] argsArray)  
    throws InvocationTargetException, IllegalAccessException  
{  
  
    if (_useStricterInvocation) {  
        final Class methodDeclaringClass = method.getDeclaringClass();  // Note: synchronized(method) call below will already NPE, so no null check.  
        if ( (AO_SETACCESSIBLE_REF != null && AO_SETACCESSIBLE_REF.equals(method)) ||  
            (AO_SETACCESSIBLE_ARR_REF != null && AO_SETACCESSIBLE_ARR_REF.equals(method)) ||  
            (SYS_EXIT_REF != null && SYS_EXIT_REF.equals(method)) ||  
            (SYS_CONSOLE_REF != null && SYS_CONSOLE_REF.equals(method)) ||  
            AccessibleObjectHandler.class.isAssignableFrom(methodDeclaringClass) ||  
            ClassResolver.class.isAssignableFrom(methodDeclaringClass) ||  
            MethodAccessor.class.isAssignableFrom(methodDeclaringClass) ||  
            MemberAccess.class.isAssignableFrom(methodDeclaringClass) ||  
            OgnlContext.class.isAssignableFrom(methodDeclaringClass) ||  
            Runtime.class.isAssignableFrom(methodDeclaringClass) ||  
            ClassLoader.class.isAssignableFrom(methodDeclaringClass) ||  
            ProcessBuilder.class.isAssignableFrom(methodDeclaringClass) ||  
            AccessibleObjectHandlerJDK9Plus.unsafeOrDescendant(methodDeclaringClass) ) {  
            throw new IllegalAccessException("........");  
        }

0x4: 投影与选择

OGNL 支持类似数据库当中的选择与投影功能。

  • 投影:选出集合当中的相同属性组合成一个新的集合。语法为 collection.{XXX},XXX 就是集合中每个元素的公共属性。
  • 选择:选择就是选择出集合当中符合条件的元素组合成新的集合。语法为 collection.{Y XXX},其中 Y 是一个选择操作符,XXX 是选择用的逻辑表达式。选择操作符有 3 种:
    • ? :选择满足条件的所有元素
    • ^:选择满足条件的第一个元素
    • $:选择满足条件的最后一个元素