OoO En ce début de soirée du vendredi 28 décembre 2007, vers 21:45, je disais:
>> I found Squirrelmail's solution. They seem to use one function for every >> possible tag in the HTML source: >> http://osdir.com/ml/mail.squirrelmail.cvs/2006-12/msg00031.html >> I'll try to implement that, and/or search for more :) > Hi Robin ! > I noticed that you have posted a patch. I have tried it but it seems > that there is no effect. I have tried with ie6 from ie4linux and I still > get the javascript popups. Did you try it succesfully on rc2? > I have used the test message from here: > http://www.topolis.lt/bugtraq/expression.eml.gz I have tried with an up-to-date IE7 and the patch provided here does not fix the issue. In fact, the source code shows there is still unsanitized strings. I have completed the patch with a function from Squirrelmail (sq_defang). I have attached the complete patch.
pgpLOigAepmuJ.pgp
Description: PGP signature
--- roundcube/program/steps/mail/func.inc 2007-10-17 08:50:28.000000000 +0200 +++ roundcube/program/steps/mail/func.inc 2008-01-22 21:59:30.000000000 +0100 @@ -481,6 +481,124 @@ return Q($out); } +/* Stolen from Squirrelmail */ +function sq_deent(&$attvalue, $regex, $hex=false){ + $ret_match = false; + preg_match_all($regex, $attvalue, $matches); + if (is_array($matches) && sizeof($matches[0]) > 0){ + $repl = Array(); + for ($i = 0; $i < sizeof($matches[0]); $i++){ + $numval = $matches[1][$i]; + if ($hex){ + $numval = hexdec($numval); + } + $repl{$matches[0][$i]} = chr($numval); + } + $attvalue = strtr($attvalue, $repl); + return true; + } else { + return false; + } +} + +/* Stolen verbatim from Squirrelmail */ +function sq_defang(&$attvalue){ + /** + * Skip this if there aren't ampersands or backslashes. + */ + if (strpos($attvalue, '&') === false + && strpos($attvalue, '\\') === false){ + return; + } + $m = false; + do { + $m = false; + $m = $m || sq_deent($attvalue, '/\�*(\d+);*/s'); + $m = $m || sq_deent($attvalue, '/\�*((\d|[a-f])+);*/si', true); + $m = $m || sq_deent($attvalue, '/\\\\(\d+)/s', true); + } while ($m == true); + $attvalue = stripslashes($attvalue); +} + +function rcmail_html_filter($html) + { + preg_match_all('/<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|\'.*?\'|[^\'">\s]+))?)+\s*|\s*)\/?>/', $html, $tags); + + /* From Squirrelmail: Translate all dangerous Unicode or Shift_JIS characters which are accepted by + * IE as regular characters. */ + $replace = array(array('ʟ', 'ʟ' ,/* L UNICODE IPA Extension */ + 'ʀ', 'ʀ' ,/* R UNICODE IPA Extension */ + 'ɴ', 'ɴ' ,/* N UNICODE IPA Extension */ + 'E', 'E' ,/* Unicode FULLWIDTH LATIN CAPITAL LETTER E */ + 'e', 'e' ,/* Unicode FULLWIDTH LATIN SMALL LETTER E */ + 'X', 'X',/* Unicode FULLWIDTH LATIN CAPITAL LETTER X */ + 'x', 'x',/* Unicode FULLWIDTH LATIN SMALL LETTER X */ + 'P', 'P',/* Unicode FULLWIDTH LATIN CAPITAL LETTER P */ + 'p', 'p',/* Unicode FULLWIDTH LATIN SMALL LETTER P */ + 'R', 'R',/* Unicode FULLWIDTH LATIN CAPITAL LETTER R */ + 'r', 'r',/* Unicode FULLWIDTH LATIN SMALL LETTER R */ + 'S', 'S',/* Unicode FULLWIDTH LATIN CAPITAL LETTER S */ + 's', 's',/* Unicode FULLWIDTH LATIN SMALL LETTER S */ + 'I', 'I',/* Unicode FULLWIDTH LATIN CAPITAL LETTER I */ + 'i', 'i',/* Unicode FULLWIDTH LATIN SMALL LETTER I */ + 'O', 'O',/* Unicode FULLWIDTH LATIN CAPITAL LETTER O */ + 'o', 'o',/* Unicode FULLWIDTH LATIN SMALL LETTER O */ + 'N', 'N',/* Unicode FULLWIDTH LATIN CAPITAL LETTER N */ + 'n', 'n',/* Unicode FULLWIDTH LATIN SMALL LETTER N */ + 'L', 'L',/* Unicode FULLWIDTH LATIN CAPITAL LETTER L */ + 'l', 'l',/* Unicode FULLWIDTH LATIN SMALL LETTER L */ + 'U', 'U',/* Unicode FULLWIDTH LATIN CAPITAL LETTER U */ + 'u', 'u',/* Unicode FULLWIDTH LATIN SMALL LETTER U */ + 'ⁿ', 'ⁿ' ,/* Unicode SUPERSCRIPT LATIN SMALL LETTER N */ + "\xEF\xBC\xA5", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER E */ + /* in unicode this is some Chinese char range */ + "\xEF\xBD\x85", /* Shift JIS FULLWIDTH LATIN SMALL LETTER E */ + "\xEF\xBC\xB8", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER X */ + "\xEF\xBD\x98", /* Shift JIS FULLWIDTH LATIN SMALL LETTER X */ + "\xEF\xBC\xB0", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER P */ + "\xEF\xBD\x90", /* Shift JIS FULLWIDTH LATIN SMALL LETTER P */ + "\xEF\xBC\xB2", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER R */ + "\xEF\xBD\x92", /* Shift JIS FULLWIDTH LATIN SMALL LETTER R */ + "\xEF\xBC\xB3", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER S */ + "\xEF\xBD\x93", /* Shift JIS FULLWIDTH LATIN SMALL LETTER S */ + "\xEF\xBC\xA9", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER I */ + "\xEF\xBD\x89", /* Shift JIS FULLWIDTH LATIN SMALL LETTER I */ + "\xEF\xBC\xAF", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER O */ + "\xEF\xBD\x8F", /* Shift JIS FULLWIDTH LATIN SMALL LETTER O */ + "\xEF\xBC\xAE", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER N */ + "\xEF\xBD\x8E", /* Shift JIS FULLWIDTH LATIN SMALL LETTER N */ + "\xEF\xBC\xAC", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER L */ + "\xEF\xBD\x8C", /* Shift JIS FULLWIDTH LATIN SMALL LETTER L */ + "\xEF\xBC\xB5", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER U */ + "\xEF\xBD\x95", /* Shift JIS FULLWIDTH LATIN SMALL LETTER U */ + "\xE2\x81\xBF", /* Shift JIS FULLWIDTH SUPERSCRIPT N */ + "\xCA\x9F", /* L UNICODE IPA Extension */ + "\xCA\x80", /* R UNICODE IPA Extension */ + "\xC9\xB4"), /* N UNICODE IPA Extension */ + array('l', 'l', 'r', 'r', 'n', 'n', 'E', 'E', 'e', 'e', 'X', 'X', 'x', 'x', + 'P', 'P', 'p', 'p', 'R', 'R', 'r', 'r', 'S', 'S', 's', 's', 'I', 'I', + 'i', 'i', 'O', 'O', 'o', 'o', 'N', 'N', 'n', 'n', 'L', 'L', 'l', 'l', + 'U', 'U', 'u', 'u', 'n', 'n', 'E', 'e', 'X', 'x', 'P', 'p', 'R', 'r', + 'S', 's', 'I', 'i', 'O', 'o', 'N', 'n', 'L', 'l', 'U', 'u', 'n', 'l', 'r', 'n')); + if ((count($tags)>3) && (count($tags[3])>0)) + foreach ($tags[3] as $nr=>$value) + { + /* Remove comments */ + $newvalue = preg_replace('/(\/\*.*\*\/)/','$2',$value); + /* Translate dangerous characters */ + $newvalue = str_replace($replace[0], $replace[1], $newvalue); + sq_defang($newvalue); + /* Rename dangerous CSS */ + $newvalue = preg_replace('/expression/i', 'idiocy', $newvalue); + $newvalue = preg_replace('/url/i', 'idiocy', $newvalue); + $newattrs = preg_replace('/'.preg_quote($value, '/').'$/', $newvalue, $tags[1][$nr]); + $newtag = preg_replace('/'.preg_quote($tags[1][$nr], '/').'/', $newattrs, $tags[0][$nr]); + $html = preg_replace('/'.preg_quote($tags[0][$nr], '/').'/', $newtag, $html); + } + + return $html; + } + function rcmail_print_body($part, $safe=FALSE, $plain=FALSE) { @@ -533,7 +651,7 @@ $body = preg_replace($remote_patterns, $remote_replaces, $body); } - return Q($body, 'show', FALSE); + return Q(rcmail_html_filter($body), 'show', FALSE); } // text/enriched
There is still some unsanitized strings but IE does not trigger any alert any more. We will use this patch as a temporary fix for Roundcube Debian package unless you see a better way to handle this issue. -- Treat end of file conditions in a uniform manner. - The Elements of Programming Style (Kernighan & Plauger)