Java OgnlMVEL and JEXL表达式注入漏洞成因及细节
字数 1457 2025-08-10 09:16:21

Java表达式注入漏洞详解:OGNL、MVEL与JEXL

前言

本文全面分析Java中常见的表达式注入漏洞类型及其原理,重点介绍OGNL(Object-Graph Navigation Language)、MVEL和JEXL三种表达式语言的特性、使用方式及安全风险。

OGNL表达式语言

背景与特点

OGNL是一种功能强大的表达式语言,具有以下特点:

  • 通过简单一致的表达式语法存取对象任意属性
  • 可调用对象方法
  • 能遍历整个对象结构图
  • 实现字段类型转化等功能
  • 使用Java反射和内省机制在运行时解析对象图

基本语法

  1. 类静态方法调用和值访问

    @[类全名(包括包路径)]@[方法名|值名]
    
  2. 访问OGNL上下文(OGNL context)和ActionContext

  3. 对象创建

    new 对象
    
  4. 容器变量访问
    使用#符号

  5. 投影和选择

    • 选择:collection.{X YYY},其中X是选择操作符(?、^、$),YYY是选择用的逻辑表达式
    • 投影:collection.{XXX},XXX是集合中每个元素的公共属性
  6. 语法树形式

    • (expression)(constant) = value
    • (constant)((expression1)(expression2))
  7. 符号区别

    • @:获取静态函数和变量
    • .:获取非静态函数
    • #:获取非静态变量

ActionContext对象

ActionContext是一个基于MAP结构的上下文对象,使用键值对描述对象属性及值。包含以下作用域:

  • request:请求作用域
  • session:会话作用域
  • application:应用作用域
  • attr:保存上述三个作用域的所有属性(重复时以request域为准)
  • paramters:保存表单提交参数
  • VALUE_STACK:值栈,保存valueStack对象

表达式解析示例

@RequestMapping("/ognl")
@ResponseBody
public String OgnlTest(@RequestParam(required = false) String expression) {
    if (expression == null) {
        return "Send request with \"expression\" parameter!";
    }
    try {
        OgnlContext ognlContext = new OgnlContext();
        Ognl.getValue(expression, ognlContext, ognlContext.getRoot());
    } catch (Exception e) {
        return Util.printStack(e);
    }
    return "OK!";
}

解析过程分析

  1. 表达式解析

    • 调用Ognl.getValue()方法
    • 内部调用parseExpression方法构建AST(抽象语法树)结构
    • 在OGNL中表现为ASTChain类数据结构
    • 不同语句被抽象为SimpleNode抽象类的各种实现类:
      • 方法调用:ASTMethod
      • 构造方法:ASTCtor
  2. 表达式求值

    • 循环调用每个节点的getValue方法
    • 核心逻辑在各节点实现的getValueBody方法中
      • ASTCtor#getValueBody:通过Class.forName获取目标类
      • ASTMethod:封装方法调用并执行

表达式注入漏洞成因

表达式注入漏洞通常发生在以下场景:

  1. 应用程序接受用户输入作为表达式直接解析
  2. 解析器未对表达式内容进行安全过滤
  3. 表达式语言功能过于强大,允许执行任意代码

攻击向量示例

攻击者可以构造恶意表达式实现:

  • 任意Java代码执行
  • 系统命令执行
  • 敏感信息泄露
  • 服务器文件系统访问

防御措施

  1. 输入验证

    • 严格限制用户输入的表达式内容
    • 使用白名单机制允许特定语法
  2. 沙箱环境

    • 在受限环境中执行表达式
    • 限制可访问的类和方法
  3. 安全配置

    • 禁用危险的功能和操作符
    • 设置适当的安全管理器
  4. 替代方案

    • 使用功能受限的表达式语言
    • 考虑使用模板引擎替代

总结

OGNL、MVEL和JEXL等表达式语言虽然提供了强大的功能,但也带来了严重的安全风险。开发人员必须充分了解这些技术的内部工作原理,在享受便利性的同时确保应用程序的安全性。通过合理的输入验证、安全配置和沙箱环境,可以有效降低表达式注入漏洞的风险。

Java表达式注入漏洞详解:OGNL、MVEL与JEXL 前言 本文全面分析Java中常见的表达式注入漏洞类型及其原理,重点介绍OGNL(Object-Graph Navigation Language)、MVEL和JEXL三种表达式语言的特性、使用方式及安全风险。 OGNL表达式语言 背景与特点 OGNL是一种功能强大的表达式语言,具有以下特点: 通过简单一致的表达式语法存取对象任意属性 可调用对象方法 能遍历整个对象结构图 实现字段类型转化等功能 使用Java反射和内省机制在运行时解析对象图 基本语法 类静态方法调用和值访问 : 访问OGNL上下文(OGNL context)和ActionContext 对象创建 : 容器变量访问 : 使用 # 符号 投影和选择 : 选择: collection.{X YYY} ,其中X是选择操作符(?、^、$),YYY是选择用的逻辑表达式 投影: collection.{XXX} ,XXX是集合中每个元素的公共属性 语法树形式 : (expression)(constant) = value (constant)((expression1)(expression2)) 符号区别 : @ :获取静态函数和变量 . :获取非静态函数 # :获取非静态变量 ActionContext对象 ActionContext是一个基于MAP结构的上下文对象,使用键值对描述对象属性及值。包含以下作用域: request :请求作用域 session :会话作用域 application :应用作用域 attr :保存上述三个作用域的所有属性(重复时以request域为准) paramters :保存表单提交参数 VALUE_STACK :值栈,保存valueStack对象 表达式解析示例 解析过程分析 表达式解析 : 调用 Ognl.getValue() 方法 内部调用 parseExpression 方法构建AST(抽象语法树)结构 在OGNL中表现为 ASTChain 类数据结构 不同语句被抽象为 SimpleNode 抽象类的各种实现类: 方法调用: ASTMethod 构造方法: ASTCtor 表达式求值 : 循环调用每个节点的 getValue 方法 核心逻辑在各节点实现的 getValueBody 方法中 ASTCtor#getValueBody :通过 Class.forName 获取目标类 ASTMethod :封装方法调用并执行 表达式注入漏洞成因 表达式注入漏洞通常发生在以下场景: 应用程序接受用户输入作为表达式直接解析 解析器未对表达式内容进行安全过滤 表达式语言功能过于强大,允许执行任意代码 攻击向量示例 攻击者可以构造恶意表达式实现: 任意Java代码执行 系统命令执行 敏感信息泄露 服务器文件系统访问 防御措施 输入验证 : 严格限制用户输入的表达式内容 使用白名单机制允许特定语法 沙箱环境 : 在受限环境中执行表达式 限制可访问的类和方法 安全配置 : 禁用危险的功能和操作符 设置适当的安全管理器 替代方案 : 使用功能受限的表达式语言 考虑使用模板引擎替代 总结 OGNL、MVEL和JEXL等表达式语言虽然提供了强大的功能,但也带来了严重的安全风险。开发人员必须充分了解这些技术的内部工作原理,在享受便利性的同时确保应用程序的安全性。通过合理的输入验证、安全配置和沙箱环境,可以有效降低表达式注入漏洞的风险。