Lucene search

K
seebugSebaoSSV:92784
HistoryMar 15, 2017 - 12:00 a.m.

Roundcube mail body of the stored cross site Vulnerability(CVE-2017-6820)

2017-03-1500:00:00
sebao
www.seebug.org
49

0.002 Low

EPSS

Percentile

58.8%

Author: Badcode, sebao (know Chong Yu 404 security lab)

Date: 2017-03-17

0x00 vulnerability overview

1. Vulnerability description

Roundcube is a widely used open source e-mail program, in the globe there are many organizations and companies are in use. On the server to successfully install Roundcube, it will provide to the user a web interface, authenticated user can through a Web browser, email. 1.1.8 version before and 1.2.4 versions prior to Roundcube the message body show the presence of stored cross site scripting vulnerability. Authorities have released the upgrade announcement is.

2. Impact version

1.1. x < 1.1.8 1.2. x < 1.2.4

0x01 vulnerability reproduction

Payload from. mario

payload

Use telnet to html form to send a packet containing the payload of the message to the target mailbox, or directly using Roundcube to send a html mail Send when using burpsuite capture the_message value into the payload you can(you can also use other way to send mail, to be noted that the payload will be escaped to).

telnet

When a user views the email can trigger a cross site scripting vulnerability.

0x02 vulnerability analysis

First look at the entire process, when the user view the messages namely action=show, index.php will contain the/program/steps/mail/show. inc,it will call$OUTPUT-&gt;send('message',false), jump to/program/include/rcmail_output_html.php the front end of the output page is generated here. Here will call the xml_command() this function loops through the template to output the desired data(label,button,message headers,message body, etc.), splice returns. Wherein the fetch message body will jump to the rcmail_message_body function.

Look under rcmail_message_body function, in the/program/steps/mail/fun. inc 1169-1329.

``php function rcmail_message_body($attrib) { …

 // fetch part of the body
 $body = $MESSAGE-&gt;get_part_body($part-&gt;mime_id, true);

 // message is cached but not exists (#1485443), or other error
 if ($body === false) {
rcmail_message_error($MESSAGE-&gt;uid);
}

 $plugin = $RCMAIL-&gt;plugins-&gt;exec_hook('message_body_prefix',
 array('part' =&gt; $part, 'prefix' =&gt; "));

 $body = rcmail_print_body($body, $part, array('safe' =&gt; $safe_mode, 'plain' =&gt; !$ RCMAIL-&gt;config-&gt;get('prefer_html')));

 if ($part-&gt;ctype_secondary == 'html') {
 $container_id = 'message-htmlpart' . (++$part_no);
 $body = rcmail_html4inline($body, $container_id, 'rcmBody', $attrs, $safe_mode);
 $div_attr = array('class' =&gt; 'message-htmlpart', 'id' =&gt; $container_id);
 $style = array();

 if (! empty($attrs)) {
 foreach ($attrs as $a_idx =&gt; $a_val)
 $style[] = $a_idx . ': '. $a_val;
 if (! empty($style))
 $div_attr['style'] = implode('; ', $style);
}

 $out .= html::div($div_attr, $plugin['prefix'] . $body);
}
else
 $out .= html::div('message-part', $plugin['prefix'] . $body);
}
}
}

return html::div($attrib, $out);

} ``

ctype_secondary the value is the message the Content-type of the second part(text/html), when ctype_secondary as html, that is, the mail is html type, it will call rcmail_html4inline function on the message content for processing. This is why you want to the html form to send the mail of the reasons. Follow up to rcmail_html4inline function

``php function rcmail_html4inline($body, $container_id, $body_class=", &$attributes=null, $allow_remote=false) { $last_style_pos = 0; $cont_id = $container_id . ($body_class ? ’ div.'.$ body_class : ");

// find STYLE tags
while (($pos = stripos($body, '&lt;style', $last_style_pos)) && ($pos2 = stripos($body, '&lt;/style&gt;', $pos))) {
 $pos = strpos($body, '&gt;', $pos) + 1;
 $len = $pos2 - $pos;

 // replace all css definitions with #container [def]
 $styles = substr($body, $pos, $len);
 $styles = rcube_utils::mod_css_styles($styles, $cont_id, $allow_remote);

 $body = substr_replace($body, $styles, $pos, $len);
 $last_style_pos = $pos2 + strlen($styles) - $len;
}

......
return $body;

``

You can see that when the message content contains style tags, the style tag content as css styles, call mod_css_styles function processing, the filter css style danger label. This is also the whole vulnerability to trigger the critical point, the style label’s value is reflected in this. Continue to follow up

``php public static function mod_css_styles($source, $container_id, $allow_remote=false) { $last_pos = 0; $replacements = new rcube_string_replacer;

 // ignore the whole block if evil styles are detected
 $source = self::xss_entity_decode($source);
 $stripped = preg_replace('/[^a-z\(:;]/i', ", $source);
 $evilexpr = 'expression|behavior|javascript:|import[^a]' . (!$ allow_remote ? '|url\(' : ");

 if (preg_match("/$evilexpr/i", $stripped)) {
 return '/* evil! */';
}

......
 return $source;
}

``

Come here, you can see that for$source call xss_entity_decode function processing, the code behind is the$source is judged and filtered.

``php public static function xss_entity_decode($content) { $out = html_entity_decode(html_entity_decode($content)); $out = preg_replace_callback(‘/\([0-9a-f]{4})/i’, array(self, ‘xss_entity_decode_callback’), $out); $out = preg_replace(‘#/*.**/# Ums’, ", $out);

 return $out;
}

``

xss_entity_decode the css of the content is decoded, the&lt;img/src=x onerror=alert(1)//for decoding, return to the&lt;img/src=x onerror=alert(1)//

The original road to return, return to the rcmail_message_body function, then the$body content below, and finally return to the rcmail_out_html.php, splice the other data output contains the payload of the page is the complete output to the front end.

body

0x03 patch analysis

patch

patch2

$content is decoded after, before return$out using a strip_tags filter,remove HTML and PHP tags.

0x04 solution

Upgrade procedure: https://roundcube.net/news/2017/03/10/updates-1.2.4-and-1.1.8-released