Thomas Bruederli
2016-01-16 97f3972c9fdcf840cc979f1d9cdc139f2da09395
Protect attachment download urls against csrf using unique request tokens (#1490642)
6 files modified
35 ■■■■ changed files
plugins/zipdownload/zipdownload.js 2 ●●● patch | view | raw | blame | history
plugins/zipdownload/zipdownload.php 6 ●●●● patch | view | raw | blame | history
program/include/rcmail.php 2 ●●●●● patch | view | raw | blame | history
program/js/app.js 18 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_message.php 3 ●●●● patch | view | raw | blame | history
program/steps/mail/get.inc 4 ●●●● patch | view | raw | blame | history
plugins/zipdownload/zipdownload.js
@@ -54,7 +54,7 @@
    // default .eml download of single message
    if (mode == 'eml') {
        var uid = rcmail.get_single_uid();
        rcmail.goto_url('viewsource', rcmail.params_from_uid(uid, {_save: 1}));
        rcmail.goto_url('viewsource', rcmail.params_from_uid(uid, {_save: 1}), true, true);
        return;
    }
plugins/zipdownload/zipdownload.php
@@ -63,7 +63,7 @@
                '_action' => 'plugin.zipdownload.attachments',
                '_mbox'   => $rcmail->output->env['mailbox'],
                '_uid'    => $rcmail->output->env['uid'],
            ));
            ), false, false, true);
            $link = html::a(array('href' => $href, 'class' => 'button zipdownload'),
                rcube::Q($this->gettext('downloadall'))
@@ -120,6 +120,10 @@
    public function download_attachments()
    {
        $rcmail    = rcmail::get_instance();
        // require CSRF protected request
        $rcmail->request_security_check(rcube_utils::INPUT_GET);
        $imap      = $rcmail->get_storage();
        $temp_dir  = $rcmail->config->get('temp_dir');
        $tmpfname  = tempnam($temp_dir, 'zipdownload');
program/include/rcmail.php
@@ -840,6 +840,8 @@
            // this need to be full url to make redirects work
            $absolute = true;
        }
        else if ($secure && ($token = $this->get_request_token()))
            $url .= $delm . '_token=' . urlencode($token);
        if ($absolute || $full) {
            // add base path to this Roundcube installation
program/js/app.js
@@ -1019,7 +1019,7 @@
            break;
        }
        this.goto_url('get', qstring+'&_download=1', false);
        this.goto_url('get', qstring+'&_download=1', false, true);
        break;
      case 'select-all':
@@ -1225,7 +1225,7 @@
      case 'download':
        if (this.env.action == 'get') {
          location.href = location.href.replace(/_frame=/, '_download=');
          location.href = this.secure_url(location.href.replace(/_frame=/, '_download='));
        }
        else if (uid = this.get_single_uid()) {
          this.goto_url('viewsource', this.params_from_uid(uid, {_save: 1}));
@@ -1437,7 +1437,7 @@
    if (task == 'mail')
      url += '&_mbox=INBOX';
    else if (task == 'logout' && !this.env.server_error) {
      url += '&_token=' + this.env.request_token;
      url = this.secure_url(url);
      this.clear_compose_data();
    }
@@ -1485,6 +1485,12 @@
    return url + '?' + name + '=' + value;
  };
  // append CSRF protection token to the given url
  this.secure_url = function(url)
  {
    return this.add_url(url, '_token', this.env.request_token);
  },
  this.is_framed = function()
  {
@@ -7894,9 +7900,11 @@
    }
  };
  this.goto_url = function(action, query, lock)
  this.goto_url = function(action, query, lock, secure)
  {
    this.redirect(this.url(action, query), lock);
    var url = this.url(action, query)
    if (secure) url = this.secure_url(url);
    this.redirect(url, lock);
  };
  this.location_href = function(url, target, frame)
program/lib/Roundcube/rcube_message.php
@@ -108,7 +108,8 @@
            'get_url'     => $this->app->url(array(
                    'action' => 'get',
                    'mbox'   => $this->folder,
                    'uid'    => $uid))
                    'uid'    => $uid),
                false, false, true)
        );
        if (!empty($this->headers->structure)) {
program/steps/mail/get.inc
@@ -129,6 +129,10 @@
            exit;
        }
        // require CSRF protected url for downloads
        if ($plugin['download'])
            $RCMAIL->request_security_check(rcube_utils::INPUT_GET);
        // overwrite modified vars from plugin
        $mimetype   = $plugin['mimetype'];
        $extensions = rcube_mime::get_mime_extensions($mimetype);