一个隐藏但广泛使用的电子邮件程序中的错误可能会导致全球多达40万台服务器面临严重攻击的风险,直到升级为止。
研究人员在周二发布的一份警告中公布了这个漏洞,漏洞在Exim邮件传输代理的所有版本中,除了4.90.1版本以上,服务器可以执行恶意代码的攻击。缓冲区溢出漏洞,编入CVE-2018-6789,位于base64解码函数中。通过向运行Exim的服务器发送特定操作的输入,攻击者可能能够远程执行代码。
Devcore安全咨询公司的研究人员写道,利用漏洞产生的单字节数据“在字符串适合某个特定长度时会覆盖一些关键数据”。 “另外,这个字节是可控制的,这使得开发更加可行。Base64解码是一个基本功能,因此这个bug很容易触发,导致远程代码执行。”
就Exim而言,Exim的开发人员在一份咨询中写道:“目前,我们不确定漏洞的严重程度。 “我们相信*一个漏洞很难,缓解措施是未知的。”
Devcore的研究人员表示多达400,000台服务器面临风险。 Shodan计算机搜索引擎上的查询发现了大量报告运行中存在漏洞的版本的服务器。开发人员在2月10日发布了版本为4.90.1的修复程序。任何使用Exim的组织都应确保其使用的是最新版本。
漏洞详情如下:
Exim Off-by-one RCE:利用完全缓解绕过的CVE-2018-6789
概述
我们在2018年2月5日报告了Exim的base64解码函数中的溢出漏洞,标识为CVE-2018-6789。 自从exim第一次提交以来就存在这个错误,因此所有版本都受到影响。 根据我们的研究,它可以用来获得预授权远程执行代码,并且至少有40万台服务器处于风险之中。 补丁版本4.90.1已经发布,我们建议立即升级exim。
受影响
所有低于4.90.1Exim版本
base64解码中有一个字节溢出
漏洞分析
这是b64decode函数中解码缓冲区长度的计算错误:
如上所示,exim分配一个3 *(len / 4)+1字节的缓冲区来存储解码后的base64数据。 但是,当输入不是有效的base64字符串且长度为4n + 3时,exim分配3n + 1,但在解码时会占用3n + 2个字节。 这会导致一个字节堆溢出(aka逐个)。
通常,这个错误是无害的,因为内存覆盖通常是未使用的。 但是,当字符串适合某些特定长度时,该字节会覆盖一些关键数据。 另外,这个字节是可控的,这使得开发更加可行。
Base64解码是这样一个基本功能,因此这个错误可以很容易地触发,导致远程代码执行。
开发
为了评估这个bug的严重性,我们开发了一个针对exim的SMTP守护进程的攻击。 以下段落描述了用于实现pre-auth远程代码执行的开发机制。 为了利用这一个字节溢出,有必要诱骗内存管理机制。 在阅读本节之前,强烈建议你具有堆栈开发的基本知识。
我们测试了这个漏洞:
Debian(stretch)和Ubuntu(zesty)
使用apt-get安装Exim4软件包的SMTP守护进程(4.89 / 4.88)
启用配置(在默认配置中未注释)CRAM-MD5身份验证器(使用base64的任何其他身份验证程序也可以运行)
基本的SMTP命令(EHLO,MAIL FROM / RCPT TO)和AUTH
内存分配
首先,我们回顾一下源代码并搜索有用的内存分配。 正如我们在前一篇文章中提到的,exim使用自定义函数进行动态分配:
函数store_free()和store_malloc()直接调用glibc的malloc()和free()。 Glibc需要一个稍大的(0x10字节)块,并将其元数据存储在每个分配的第一个0x10字节(x86-64)中,然后返回数据的位置。 下面的插图描述了块的结构:
元数据包括前一个块的大小(正好在内存中的那个),当前块的大小和一些标志。 大小的前三位用于存储标志。 在这个例子中,0x81的大小意味着当前块是0x80字节,并且前一个块正在使用中。
在exim中使用的大部分已发布的块被放入一个双向链表中,称为未排序的bin。 Glibc根据标志维护它,并将相邻的已发布块合并为一个更大的块以避免碎片化。 对于每个分配请求,glibc都会以FIFO(先进先出)顺序检查这些块,并重新使用这些块。
对于一些性能问题,exim通过store_get(),store_release(),store_extend()和store_reset()维护自己的链表结构。
storeblocks的主要特点是每块至少有0x2000字节,这成为我们利用的限制。 请注意,storeblock也是块的数据。 因此,如果我们查看记忆,就像:
这里我们列出用来排列堆数据的函数:
EHLO主机名,对于每个EHLO(或HELO)命令,exim将主机名的指针存储在sender_host_name中。
store_free()旧名称
store_malloc()为新名称
无法识别的命令
对于每个无法识别的带有不可打印字符的命令,exim都会分配一个缓冲区来将其转换为可打印的store_get()存储错误消息
AUTH
在大多数身份验证过程中,exim使用base64编码与客户端进行通信。 编码和解码字符串存储在由store_get()分配的缓冲区中。
store_get()用于字符串
可以包含不可打印的字符,NULL字节
不一定是NULL终止
在EHLO / HELO,MAIL,RCPT中重置
当命令正确完成时,调用smtp_reset()。 该函数调用store_reset()将块链重置为重置点,这意味着所有store_get()在last命令后分配的storeblock被释放。
store_reset()重置点(在函数的开始处设置)
释放块一次添加
利用步骤
为了充分利用这一点,解码后的base64数据下的块应该易于释放和控制。 经过多次尝试,我们发现sender_host_name是更好的选择。 我们安排堆布局,为base64数据留下一个空闲的块,高于sender_host_name。
第一步,把一个巨大的块放入未排序的unsorted bin
首先,我们发送一个带有巨大主机名称的EHLO消息,以使其分配和释放,在未排序的容器中留下一个0x6060长度(3个存储块长)块。
第二步,剪下第一个storeblock
然后我们发送一个无法识别的字符串来触发store_get()并在释放的块内分配storeblock。
第三步,剪下第二个存储区并释放第一个存储区
我们再次发送EHLO消息以获得第二个存储区。 由于EHLO完成后调用了smtp_reset,所以第一个块被顺序释放。
堆布局准备好后,我们可以使用off-by-one覆盖原始块大小。 我们将0x2021修改为0x20f1,这稍微扩展了块。
第四步,发送base64数据并逐个触发
要逐个触发,我们启动一个AUTH命令来发送base64数据。 溢出字节正好覆盖下一个块的第一个字节并扩展下一个块。
第五步,形成合理的块大小
由于块已扩展,下一块块的开始被更改为原始块的内部。 因此,我们需要让它看起来像一个正常的块来通过glibc的理智检查。 我们在这里发送另一个base64字符串,因为它需要空字节和不可打印字符来伪造块大小。
第六步,释放扩展块
要控制扩展块的内容,我们需要首先释放块,因为我们无法直接编辑块。 也就是说,我们应该发送一个新的EHLO消息来释放旧的主机名。 但是,正常的EHLO消息在成功之后会调用smtp_reset,这可能会导致程序中止或崩溃。 为了避免这种情况,我们发送一个无效的主机名称,如+。
第七步,覆盖重叠的存储区块的下一个指针
块发布后,我们可以使用AUTH检索它并覆盖部分重叠的存储块。 这里我们使用一种称为部分写入的技巧。 有了这个,我们可以在不破坏ASLR(地址空间布局随机化)的情况下修改指针。 我们部分地改变了包含ACL(访问控制列表)字符串的storeblock的下一个指针。 ACL字符串由一组全局指针指向,例如:
这些指针在exim进程开始时初始化,根据配置进行设置。 例如,如果configure中有一行acl_smtp_mail = acl_check_mail,则指针acl_smtp_mail指向字符串acl_check_mail。 无论何时使用MAIL FROM,exim执行ACL检查,首先扩展acl_check_mail。 在扩展时,exim尝试在遇到$ }时执行命令,所以只要我们控制ACL字符串,就可以实现代码执行。 另外,我们不需要直接劫持程序控制流程,因此我们可以轻松地绕过诸如PIE(位置独立可执行文件),NX等缓解措施。
第八步,重置存储区块并检索ACL存储区块
现在,ACL存储块位于链接列表链中。 一旦smtp_reset()被触发,它将被释放,然后我们可以通过分配多个块来再次检索它。
第九步,覆盖ACL字符串并触发ACL检查
最后,我们覆盖包含ACL字符串的整个块。 现在我们发送诸如EHLO,MAIL,RCPT等命令来触发ACL检查。 一旦我们触及配置中定义的acl,我们就可以实现远程代码执行。
修复方法
升级到4.90.1或以上
时间线
2018年2月5日09:10报告给Exim
2011年2月6日23:23 CVE收到
2018年2月10日18:00发布补丁
Credits
DEVHORE研究团队Meh发现的漏洞。
参考
https://exim.org/static/doc/security/CVE-2018-6789.txt
https://git.exim.org/exim.git/commit/cf3cd306062a08969c41a1cdd32c6855f1abecf1
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-6789
http://www.openwall.com/lists/oss-security/2018/02/07/2
https://devco.re/blog/2018/03/06/exim-off-by-one-RCE-exploiting-CVE-2018-6789-en/
领取专属 10元无门槛券
私享最新 技术干货