Changeset 5509 in subversion


Ignore:
Timestamp:
Nov 29, 2011 5:16:42 AM (18 months ago)
Author:
thomasb
Message:

Content filter for embedded attachments to protect from XSS on IE<=8 (#1487895)

Location:
trunk/roundcubemail
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/roundcubemail/CHANGELOG

    r5498 r5509  
    22=========================== 
    33 
     4- Add content filter for embedded attachments to protect from XSS on IE (#1487895) 
    45- Use strpos() instead of strstr() when possible (#1488211) 
    56- Fix handling HTML entities when converting HTML to text (#1488212) 
  • trunk/roundcubemail/program/include/rcube_message.php

    r5371 r5509  
    143143     * @return string URL or false if part does not exist 
    144144     */ 
    145     public function get_part_url($mime_id) 
     145    public function get_part_url($mime_id, $embed = false) 
    146146    { 
    147147        if ($this->mime_parts[$mime_id]) 
    148             return $this->opt['get_url'] . '&_part=' . $mime_id; 
     148            return $this->opt['get_url'] . '&_part=' . $mime_id . ($embed ? '&_embed=1' : ''); 
    149149        else 
    150150            return false; 
     
    512512 
    513513                foreach ($this->inline_parts as $inline_object) { 
    514                     $part_url = $this->get_part_url($inline_object->mime_id); 
     514                    $part_url = $this->get_part_url($inline_object->mime_id, true); 
    515515                    if ($inline_object->content_id) 
    516516                        $a_replaces['cid:'.$inline_object->content_id] = $part_url; 
  • trunk/roundcubemail/program/steps/mail/func.inc

    r5490 r5509  
    552552 * @return string Clean HTML 
    553553 */ 
    554 function rcmail_wash_html($html, $p = array(), $cid_replaces) 
     554function rcmail_wash_html($html, $p, $cid_replaces) 
    555555{ 
    556556  global $REMOTE_OBJECTS; 
     
    10691069        $out .= html::tag('hr') . html::p(array('align' => "center"), 
    10701070          html::img(array( 
    1071             'src' => $MESSAGE->get_part_url($attach_prop->mime_id), 
     1071            'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true), 
    10721072            'title' => $attach_prop->filename, 
    10731073            'alt' => $attach_prop->filename, 
  • trunk/roundcubemail/program/steps/mail/get.inc

    r5490 r5509  
    147147      header("Content-Disposition: $disposition; filename=\"$filename\""); 
    148148 
    149       // turn off output buffering and print part content 
    150       if ($part->body) 
    151         echo $part->body; 
    152       else if ($part->size) 
    153         $IMAP->get_message_part($MESSAGE->uid, $part->mime_id, $part, true); 
     149      // do content filtering to avoid XSS through fake images 
     150      if (!empty($_REQUEST['_embed']) && $browser->ie && $browser->ver <= 8) { 
     151        if ($part->body) 
     152          echo preg_match('/<(script|iframe|object)/i', $part->body) ? '' : $part->body; 
     153        else if ($part->size) { 
     154          $stdout = fopen('php://output', 'w'); 
     155          stream_filter_register('rcube_content', 'rcube_content_filter') or die('Failed to register content filter'); 
     156          stream_filter_append($stdout, 'rcube_content'); 
     157          $IMAP->get_message_part($MESSAGE->uid, $part->mime_id, $part, false, $stdout); 
     158        } 
     159      } 
     160      else { 
     161        // turn off output buffering and print part content 
     162        if ($part->body) 
     163          echo $part->body; 
     164        else if ($part->size) 
     165          $IMAP->get_message_part($MESSAGE->uid, $part->mime_id, $part, true); 
     166      } 
    154167    } 
    155168 
     
    179192 
    180193 
     194 
     195/** 
     196 * PHP stream filter to detect html/javascript code in attachments 
     197 */ 
     198class rcube_content_filter extends php_user_filter 
     199{ 
     200  private $buffer = ''; 
     201  private $cutoff = 2048; 
     202 
     203  function onCreate() 
     204  { 
     205    $this->cutoff = rand(2048, 3027); 
     206    return true; 
     207  } 
     208 
     209  function filter($in, $out, &$consumed, $closing) 
     210  { 
     211    while ($bucket = stream_bucket_make_writeable($in)) { 
     212      $this->buffer .= $bucket->data; 
     213 
     214      // check for evil content and abort 
     215      if (preg_match('/<(script|iframe|object)/i', $this->buffer)) 
     216        return PSFS_ERR_FATAL; 
     217 
     218      // keep buffer small enough 
     219      if (strlen($this->buffer) > 4096) 
     220        $this->buffer = substr($this->buffer, $this->cutoff); 
     221 
     222      $consumed += $bucket->datalen; 
     223      stream_bucket_append($out, $bucket); 
     224    } 
     225 
     226    return PSFS_PASS_ON; 
     227  } 
     228} 
     229 
  • trunk/roundcubemail/program/steps/mail/show.inc

    r5409 r5509  
    133133        $ol .= html::tag('li', null, 
    134134          html::a(array( 
    135             'href' => $MESSAGE->get_part_url($attach_prop->mime_id), 
     135            'href' => $MESSAGE->get_part_url($attach_prop->mime_id, false), 
    136136            'onclick' => sprintf( 
    137137              'return %s.command(\'load-attachment\',{part:\'%s\', mimetype:\'%s\'},this)', 
Note: See TracChangeset for help on using the changeset viewer.