From e3dd5b66d236867572e68fcb80281e9268a0cfb0 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Mon, 9 Apr 2018 09:07:27 +0200 Subject: [PATCH] Fix check_request() bypass in places using get_uids() [CVE-2018-9846] (#6238) --- CHANGELOG | 1 + plugins/archive/archive.php | 6 ++---- plugins/managesieve/managesieve.php | 5 +++-- plugins/markasjunk/markasjunk.php | 2 +- plugins/zipdownload/zipdownload.php | 4 ++-- program/include/rcmail.php | 12 +++++++----- program/steps/mail/copy.inc | 2 +- program/steps/mail/mark.inc | 9 +++++---- program/steps/mail/move_del.inc | 4 ++-- 9 files changed, 24 insertions(+), 21 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f34306737..73a7ce68e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,7 @@ CHANGELOG Roundcube Webmail - Fix PHP 7.2: count(): Parameter must be an array in enchant-based spellchecker (#6234) - Fix possible IMAP command injection and type juggling vulnerabilities (#6229) - Enigma: Fix key selection for signing +- Fix check_request() bypass in places using get_uids() [CVE-2018-9846] (#6238) RELEASE 1.3.5 ------------- diff --git a/plugins/archive/archive.php b/plugins/archive/archive.php index 286df074f..58a102e81 100644 --- a/plugins/archive/archive.php +++ b/plugins/archive/archive.php @@ -127,9 +127,7 @@ class archive extends rcube_plugin $archive_type = $rcmail->config->get('archive_type', ''); $archive_folder = $rcmail->config->get('archive_mbox'); $archive_prefix = $archive_folder . $delimiter; - $current_mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST); $search_request = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GPC); - $uids = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST); // count messages before changing anything if ($_POST['_from'] != 'show') { @@ -149,8 +147,8 @@ class archive extends rcube_plugin 'destinations' => array(), ); - foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) { - if (!$archive_folder || strpos($mbox, $archive_prefix) === 0) { + foreach (rcmail::get_uids(null, null, $multifolder, rcube_utils::INPUT_POST) as $mbox => $uids) { + if (!$archive_folder || strpos($mbox, $archive_prefix) === 0) { $count = count($uids); continue; } diff --git a/plugins/managesieve/managesieve.php b/plugins/managesieve/managesieve.php index c8241303c..259e91b09 100644 --- a/plugins/managesieve/managesieve.php +++ b/plugins/managesieve/managesieve.php @@ -189,9 +189,10 @@ class managesieve extends rcube_plugin */ function managesieve_actions() { + $uids = rcmail::get_uids(null, null, $multifolder, rcube_utils::INPUT_POST); + // handle fetching email headers for the new filter form - if ($uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST)) { - $uids = rcmail::get_uids(); + if (!empty($uids)) { $mailbox = key($uids); $message = new rcube_message($uids[$mailbox][0], $mailbox); $headers = $this->parse_headers($message->headers); diff --git a/plugins/markasjunk/markasjunk.php b/plugins/markasjunk/markasjunk.php index aff3acc84..b022f3bb9 100644 --- a/plugins/markasjunk/markasjunk.php +++ b/plugins/markasjunk/markasjunk.php @@ -62,7 +62,7 @@ class markasjunk extends rcube_plugin $rcmail = rcmail::get_instance(); $storage = $rcmail->get_storage(); - foreach (rcmail::get_uids() as $mbox => $uids) { + foreach (rcmail::get_uids(null, null, $multifolder, rcube_utils::INPUT_POST) as $mbox => $uids) { $storage->unset_flag($uids, 'NONJUNK', $mbox); $storage->set_flag($uids, 'JUNK', $mbox); } diff --git a/plugins/zipdownload/zipdownload.php b/plugins/zipdownload/zipdownload.php index 383d40063..4759549f9 100644 --- a/plugins/zipdownload/zipdownload.php +++ b/plugins/zipdownload/zipdownload.php @@ -175,8 +175,8 @@ class zipdownload extends rcube_plugin { $rcmail = rcmail::get_instance(); - if ($rcmail->config->get('zipdownload_selection') && !empty($_POST['_uid'])) { - $messageset = rcmail::get_uids(); + if ($rcmail->config->get('zipdownload_selection')) { + $messageset = rcmail::get_uids(null, null, $multi, rcube_utils::INPUT_POST); if (count($messageset)) { $this->_download_messages($messageset); } diff --git a/program/include/rcmail.php b/program/include/rcmail.php index e95ab7c47..3f739f564 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -2393,16 +2393,17 @@ class rcmail extends rcube * @param string $uids UID value to decode * @param string $mbox Default mailbox value (if not encoded in UIDs) * @param bool $is_multifolder Will be set to True if multi-folder request + * @param int $mode Request mode. Default: rcube_utils::INPUT_GPC. * * @return array List of message UIDs per folder */ - public static function get_uids($uids = null, $mbox = null, &$is_multifolder = false) + public static function get_uids($uids = null, $mbox = null, &$is_multifolder = false, $mode = null) { // message UID (or comma-separated list of IDs) is provided in // the form of -[,-]* - $_uid = $uids ?: rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GPC); - $_mbox = $mbox ?: (string) rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC); + $_uid = $uids ?: rcube_utils::get_input_value('_uid', $mode ?: rcube_utils::INPUT_GPC); + $_mbox = $mbox ?: (string) rcube_utils::get_input_value('_mbox', $mode ?: rcube_utils::INPUT_GPC); // already a hash array if (is_array($_uid) && !isset($_uid[0])) { @@ -2421,8 +2422,9 @@ class rcmail extends rcube } } else { - if (is_string($_uid)) + if (is_string($_uid)) { $_uid = explode(',', $_uid); + } // create a per-folder UIDs array foreach ((array)$_uid as $uid) { @@ -2437,7 +2439,7 @@ class rcmail extends rcube if ($uid == '*') { $result[$mbox] = $uid; } - else { + else if (preg_match('/^[0-9:.]+$/', $uid)) { $result[$mbox][] = $uid; } } diff --git a/program/steps/mail/copy.inc b/program/steps/mail/copy.inc index 68fa24653..d8212757a 100644 --- a/program/steps/mail/copy.inc +++ b/program/steps/mail/copy.inc @@ -29,7 +29,7 @@ if (!empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) { $target = rcube_utils::get_input_value('_target_mbox', rcube_utils::INPUT_POST, true); $sources = array(); - foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) { + foreach (rcmail::get_uids(null, null, $multifolder, rcube_utils::INPUT_POST) as $mbox => $uids) { if ($mbox === $target) { $copied++; } diff --git a/program/steps/mail/mark.inc b/program/steps/mail/mark.inc index 215722169..1cb8091a2 100644 --- a/program/steps/mail/mark.inc +++ b/program/steps/mail/mark.inc @@ -65,7 +65,7 @@ if ($_uids && $flag) { $input = array($mbox => '*'); } else { - $input = rcmail::get_uids(); + $input = rcmail::get_uids(null, null, $dummy, rcube_utils::INPUT_POST); } foreach ($input as $mbox => $uids) { @@ -88,9 +88,10 @@ if ($_uids && $flag) { } if ($flag == 'DELETED' && $read_deleted && !empty($_POST['_ruid'])) { - $ruids = rcube_utils::get_input_value('_ruid', rcube_utils::INPUT_POST); - foreach (rcmail::get_uids($ruids) as $mbox => $uids) { - $read += (int)$RCMAIL->storage->set_flag($uids, 'SEEN', $mbox); + if ($ruids = rcube_utils::get_input_value('_ruid', rcube_utils::INPUT_POST)) { + foreach (rcmail::get_uids($ruids) as $mbox => $uids) { + $read += (int)$RCMAIL->storage->set_flag($uids, 'SEEN', $mbox); + } } if ($read && !$skip_deleted) { diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc index abb74dddc..23d8af658 100644 --- a/program/steps/mail/move_del.inc +++ b/program/steps/mail/move_del.inc @@ -39,7 +39,7 @@ if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_targe $target = rcube_utils::get_input_value('_target_mbox', rcube_utils::INPUT_POST, true); $success = true; - foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) { + foreach (rcmail::get_uids(null, null, $multifolder, rcube_utils::INPUT_POST) as $mbox => $uids) { if ($mbox === $target) { $count += is_array($uids) ? count($uids) : 1; } @@ -73,7 +73,7 @@ if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_targe } // delete messages else if ($RCMAIL->action == 'delete' && !empty($_POST['_uid'])) { - foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) { + foreach (rcmail::get_uids(null, null, $multifolder, rcube_utils::INPUT_POST) as $mbox => $uids) { $del += (int)$RCMAIL->storage->delete_message($uids, $mbox); $count += is_array($uids) ? count($uids) : 1; $sources[] = $mbox;