Better CSS url() validation

pull/1/head
thomascube 13 years ago
parent 67e0c90fce
commit 854397b216

@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- Make Roundcube render the Email Standards Project Acid Test correctly
- Deprecate $DB, $USER, $IMAP global variables, Use $RCMAIL instead
- Add option to set default font for HTML message (#1484137)
- Fix issues with big memory allocation of IMAP results

@ -891,15 +891,29 @@ function rcmail_mod_css_styles($source, $container_id, $allow_remote=false)
// ignore the whole block if evil styles are detected
$source = rcmail_xss_entity_decode($source);
$stripped = preg_replace('/[^a-z\(:;]/i', '', $source);
$evilexpr = 'expression|behavior' . (!$allow_remote ? '|url\(|import[^a]' : '');
if (preg_match("/$evilexpr/i", $stripped) // don't accept No-Gos
|| (strpos($stripped, 'url(') && !preg_match('!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Ui', $source))) // only allow clean urls
$evilexpr = 'expression|behavior|javascript:|import[^a]' . (!$allow_remote ? '|url\(' : '');
if (preg_match("/$evilexpr/i", $stripped))
return '/* evil! */';
// cut out all contents between { and }
while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos)))
{
$key = $replacements->add(substr($source, $pos+1, $pos2-($pos+1)));
while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos))) {
$styles = substr($source, $pos+1, $pos2-($pos+1));
// check every line of a style block...
if ($allow_remote) {
$a_styles = preg_split('/;[\r\n]*/', $styles, -1, PREG_SPLIT_NO_EMPTY);
foreach ($a_styles as $line) {
$stripped = preg_replace('/[^a-z\(:;]/i', '', $line);
// ... and only allow strict url() values
if (stripos($stripped, 'url(') && !preg_match('!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Uims', $line)) {
$a_styles = array('/* evil! */');
break;
}
}
$styles = join(";\n", $a_styles);
}
$key = $replacements->add($styles);
$source = substr($source, 0, $pos+1) . $replacements->get_replacement($key) . substr($source, $pos2, strlen($source)-$pos2);
$last_pos = $pos+2;
}

@ -834,8 +834,8 @@ function rcmail_washtml_callback($tagname, $attrib, $content, $washtml)
$stripped = preg_replace('/[^a-zA-Z\(:;]/', '', rcmail_xss_entity_decode($content));
// now check for evil strings like expression, behavior or url()
if (!preg_match('/expression|behavior/i', $stripped)) {
if (!$washtml->get_config('allow_remote') && preg_match('/url\(|import[^a]/i', $stripped))
if (!preg_match('/expression|behavior|javascript:|import[^a]/i', $stripped)) {
if (!$washtml->get_config('allow_remote') && stripos($stripped, 'url('))
$washtml->extlinks = true;
else
$out = html::tag('style', array('type' => 'text/css'), $content);

Loading…
Cancel
Save