summaryrefslogtreecommitdiff
path: root/program
diff options
context:
space:
mode:
Diffstat (limited to 'program')
-rw-r--r--program/include/main.inc19
-rw-r--r--program/steps/mail/func.inc15
2 files changed, 30 insertions, 4 deletions
diff --git a/program/include/main.inc b/program/include/main.inc
index 87c727700..0453b14ad 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -597,7 +597,8 @@ function rcmail_mod_css_styles($source, $container_id, $base_url = '')
$last_pos = 0;
// ignore the whole block if evil styles are detected
- if (stristr($source, 'expression') || stristr($source, 'behavior'))
+ $stripped = preg_replace('/[^a-z\(:]/', '', rcmail_xss_entitiy_decode($source));
+ if (preg_match('/expression|behavior|url\(|import/', $stripped))
return '';
// cut out all contents between { and }
@@ -633,6 +634,22 @@ function rcmail_mod_css_styles($source, $container_id, $base_url = '')
/**
+ * Decode escaped entities used by known XSS exploits.
+ * See http://downloads.securityfocus.com/vulnerabilities/exploits/26800.eml for examples
+ *
+ * @param string CSS content to decode
+ * @return string Decoded string
+ */
+function rcmail_xss_entitiy_decode($content)
+{
+ $out = html_entity_decode(html_entity_decode($content));
+ $out = preg_replace('/\\\00([a-z0-9]{2})/ie', "chr(hexdec('\\1'))", $out);
+ $out = preg_replace('#/\*.+\*/#Um', '', $out);
+ return $out;
+}
+
+
+/**
* Compose a valid attribute string for HTML tags
*
* @param array Named tag attributes
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 7de78a1ef..6a885a07c 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -602,15 +602,14 @@ function rcmail_print_body($part, $p = array())
$wash_opts['html_elements'] = array('html','head','title','body');
}
- /* CSS styles need to be sanitized!
+ // allow CSS styles, will be sanitized by rcmail_washtml_callback()
if ($p['safe']) {
$wash_opts['html_elements'][] = 'style';
- $wash_opts['html_attribs'] = array('type');
}
- */
$washer = new washtml($wash_opts);
$washer->add_callback('form', 'rcmail_washtml_callback');
+ $washer->add_callback('style', 'rcmail_washtml_callback');
$body = $washer->wash($html);
$REMOTE_OBJECTS = $washer->extlinks;
@@ -698,6 +697,16 @@ function rcmail_washtml_callback($tagname, $attrib, $content)
$out = html::div('form', $content);
break;
+ case 'style':
+ // decode all escaped entities and reduce to ascii strings
+ $stripped = preg_replace('/[^a-zA-Z\(:]/', '', rcmail_xss_entitiy_decode($source));
+
+ // now check for evli strings like expression, behavior or url()
+ if (!preg_match('/expression|behavior|url\(|import/', $css)) {
+ $out = html::tag('style', array('type' => 'text/css'), $content);
+ break;
+ }
+
default:
$out = '';
}