0x00 漏洞背景
2020年01月29日, OpenSMTPD 官方在 github 代码仓库提交了针对 CVE-2020-7247
漏洞的修复。
CVE-2020-7247
是 OpenSMTPD 在实现 RFC 5321 的过程中对 发件人/收件人 校验不严而导致的。
OpenSMTPD 是面向 unix操作系统(BSD, MacOS, GNU/Linux) 的一个 smtp 服务程序,遵循 RFC 5321 SMTP 协议。
OpenSMTPD 最初是为OpenBSD操作系统开发的,由于其开源的特性,进而分发到了其他 unix 平台。
OpenSMTPD 是OpenBSD项目的一部分。根据ISC许可,该软件可免费供所有人使用和重用。
360CERT判断漏洞等级为中危,影响面有限。
但由于默认配置配置下就会遭到攻击。还请服务管理/运维人员及时做好自查自检工作。
0x01 漏洞详情
Qualys
是提交该漏洞的团队。其分析问题出现在 smtp_mailaddr
函数
smtp_mailaddr
函数负责校验发件人(MAIL FROM)和收件人(RCPT TO)邮件地址
usr.sbin/smtpd/smtp_session.c
static int
smtp_mailaddr(struct mailaddr *maddr, char *line, int mailfrom, char **args,
const char *domain)
{
...
if (!valid_localpart(maddr->user) ||
!valid_domainpart(maddr->domain)) {
/* accept empty return-path in MAIL FROM, required for bounces */
if (mailfrom && maddr->user[0] == '\0' && maddr->domain[0] == '\0')
return (1);
/* no user-part, reject */
if (maddr->user[0] == '\0')
return (0);
/* no domain, local user */
if (maddr->domain[0] == '\0') {
(void)strlcpy(maddr->domain, domain,
sizeof(maddr->domain));
return (1);
}
return (0);
}
return (1);
}
可以看到 valid_localpart
这一校验。用于验证是否进行本地分发(例如: 发送给本地用户 guest)。
如果maddr->user
无效(!valid_localpart为true
),且maddr->domain[0]
为空。smtp_mailaddr
会添加默认域 并返回1
。
这就导致程序会错误的进行下去,并且开始本地投递流程。
而本地投递流程中,依靠mda_unpriv
函数进行本地命令拼接并执行。
// command 组成
asprintf(&dispatcher->u.local.command,
"/usr/libexec/mail.local -f %%{mbox.from} %%{user.username}");
// command 执行
execle("/bin/sh", "/bin/sh", "-c", mda_command, (char *)NULL, mda_environ);
因为使用 sh 进行命令执行,则如果引入了 ;
这一特殊符号的话就能额外执行命令。
上述存在问题的代码在2018年5月提交的代码中引入。许多发行版可能仍在使用旧版本的库,故不受此问题的影响。
例如,只有Debian的develop分支受此问题影响,而Debian稳定分支不受此影响。因为其使用了更为陈旧的版本。
0x02 修复建议
及时升级到 OpenSMTPD
6.6.2p1 版本。
下载地址如下
OpenSMTPD 6.6.2p1 portable release
0x03 时间线
2020-01-29 OpenSMTPD 发布安全更新
2020-01-30 360CERT发布预警