summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorDavid Rothstein <drothstein@gmail.com>2015-03-18 15:20:37 -0400
committerDavid Rothstein <drothstein@gmail.com>2015-03-18 15:20:37 -0400
commitb44056d2f8e8c71d35c85ec5c2fb8f7c8a02d8a8 (patch)
tree466ec33c9527f1eaffd1b37031af6047d606cd60 /includes
parent81586d9e9d04dcee487c50de426c04221899b6d0 (diff)
downloadbrdo-b44056d2f8e8c71d35c85ec5c2fb8f7c8a02d8a8.tar.gz
brdo-b44056d2f8e8c71d35c85ec5c2fb8f7c8a02d8a8.tar.bz2
Drupal 7.35
Diffstat (limited to 'includes')
-rw-r--r--includes/bootstrap.inc22
-rw-r--r--includes/common.inc46
2 files changed, 55 insertions, 13 deletions
diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index 744fc8fe7..b33f950f4 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -8,7 +8,7 @@
/**
* The current system version.
*/
-define('VERSION', '7.34');
+define('VERSION', '7.35');
/**
* Core API compatibility.
@@ -2497,6 +2497,26 @@ function _drupal_bootstrap_variables() {
// Load bootstrap modules.
require_once DRUPAL_ROOT . '/includes/module.inc';
module_load_all(TRUE);
+
+ // Sanitize the destination parameter (which is often used for redirects) to
+ // prevent open redirect attacks leading to other domains. Sanitize both
+ // $_GET['destination'] and $_REQUEST['destination'] to protect code that
+ // relies on either, but do not sanitize $_POST to avoid interfering with
+ // unrelated form submissions. The sanitization happens here because
+ // url_is_external() requires the variable system to be available.
+ if (isset($_GET['destination']) || isset($_REQUEST['destination'])) {
+ require_once DRUPAL_ROOT . '/includes/common.inc';
+ // If the destination is an external URL, remove it.
+ if (isset($_GET['destination']) && url_is_external($_GET['destination'])) {
+ unset($_GET['destination']);
+ unset($_REQUEST['destination']);
+ }
+ // If there's still something in $_REQUEST['destination'] that didn't come
+ // from $_GET, check it too.
+ if (isset($_REQUEST['destination']) && (!isset($_GET['destination']) || $_REQUEST['destination'] != $_GET['destination']) && url_is_external($_REQUEST['destination'])) {
+ unset($_REQUEST['destination']);
+ }
+ }
}
/**
diff --git a/includes/common.inc b/includes/common.inc
index 20cc82be1..ad2a34541 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -2214,14 +2214,20 @@ function url($path = NULL, array $options = array()) {
'prefix' => ''
);
+ // A duplicate of the code from url_is_external() to avoid needing another
+ // function call, since performance inside url() is critical.
if (!isset($options['external'])) {
- // Return an external link if $path contains an allowed absolute URL. Only
- // call the slow drupal_strip_dangerous_protocols() if $path contains a ':'
- // before any / ? or #. Note: we could use url_is_external($path) here, but
- // that would require another function call, and performance inside url() is
- // critical.
+ // Return an external link if $path contains an allowed absolute URL. Avoid
+ // calling drupal_strip_dangerous_protocols() if there is any slash (/),
+ // hash (#) or question_mark (?) before the colon (:) occurrence - if any -
+ // as this would clearly mean it is not a URL. If the path starts with 2
+ // slashes then it is always considered an external URL without an explicit
+ // protocol part.
$colonpos = strpos($path, ':');
- $options['external'] = ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && drupal_strip_dangerous_protocols($path) == $path);
+ $options['external'] = (strpos($path, '//') === 0)
+ || ($colonpos !== FALSE
+ && !preg_match('![/?#]!', substr($path, 0, $colonpos))
+ && drupal_strip_dangerous_protocols($path) == $path);
}
// Preserve the original path before altering or aliasing.
@@ -2259,6 +2265,11 @@ function url($path = NULL, array $options = array()) {
return $path . $options['fragment'];
}
+ // Strip leading slashes from internal paths to prevent them becoming external
+ // URLs without protocol. /example.com should not be turned into
+ // //example.com.
+ $path = ltrim($path, '/');
+
global $base_url, $base_secure_url, $base_insecure_url;
// The base_url might be rewritten from the language rewrite in domain mode.
@@ -2336,10 +2347,15 @@ function url($path = NULL, array $options = array()) {
*/
function url_is_external($path) {
$colonpos = strpos($path, ':');
- // Avoid calling drupal_strip_dangerous_protocols() if there is any
- // slash (/), hash (#) or question_mark (?) before the colon (:)
- // occurrence - if any - as this would clearly mean it is not a URL.
- return $colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && drupal_strip_dangerous_protocols($path) == $path;
+ // Avoid calling drupal_strip_dangerous_protocols() if there is any slash (/),
+ // hash (#) or question_mark (?) before the colon (:) occurrence - if any - as
+ // this would clearly mean it is not a URL. If the path starts with 2 slashes
+ // then it is always considered an external URL without an explicit protocol
+ // part.
+ return (strpos($path, '//') === 0)
+ || ($colonpos !== FALSE
+ && !preg_match('![/?#]!', substr($path, 0, $colonpos))
+ && drupal_strip_dangerous_protocols($path) == $path);
}
/**
@@ -2636,7 +2652,10 @@ function drupal_deliver_html_page($page_callback_result) {
// Keep old path for reference, and to allow forms to redirect to it.
if (!isset($_GET['destination'])) {
- $_GET['destination'] = $_GET['q'];
+ // Make sure that the current path is not interpreted as external URL.
+ if (!url_is_external($_GET['q'])) {
+ $_GET['destination'] = $_GET['q'];
+ }
}
$path = drupal_get_normal_path(variable_get('site_404', ''));
@@ -2665,7 +2684,10 @@ function drupal_deliver_html_page($page_callback_result) {
// Keep old path for reference, and to allow forms to redirect to it.
if (!isset($_GET['destination'])) {
- $_GET['destination'] = $_GET['q'];
+ // Make sure that the current path is not interpreted as external URL.
+ if (!url_is_external($_GET['q'])) {
+ $_GET['destination'] = $_GET['q'];
+ }
}
$path = drupal_get_normal_path(variable_get('site_403', ''));