summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Eckhofer <felix@eckhofer.com>2014-03-26 14:13:40 +0100
committerThomas Bruederli <thomas@roundcube.net>2014-04-25 18:40:53 +0200
commitf58a294949547ed132bf3cdb5815b68c659b992a (patch)
tree2285e1abf79f45dc7bbc0222651363f4eaf50165
parentd71a711ab06483e62b1a7343e296ef8639352689 (diff)
Add config variable 'proxy_whitelist'
HTTP headers X_FORWARDED_* and X_REAL_IP are only evaluated when received from an IP listed in proxy_whitelist. Furthermore, only the last non-trusted IP from X-Forwarded-For is used in place of the real ip. Without this, an attacker can easily spoof the headers and control the result of the ip or ssl check. This fixes several problems with [3a4c9f42], [4d480b36] and [a520f331] as mentioned in #1489729. Conflicts: CHANGELOG
-rw-r--r--CHANGELOG1
-rw-r--r--config/defaults.inc.php4
-rw-r--r--program/lib/Roundcube/rcube_utils.php25
3 files changed, 23 insertions, 7 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 1cfb4d771..23b349960 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -15,6 +15,7 @@ CHANGELOG Roundcube Webmail
- Fix missing Mail-Followup-To header in sent mail (#1489829)
- Fix error when spell-checking an empty text (#1489831)
- Avoid popupmenus being closed when scrollbar is clicked (#1489832)
+- Add proxy_whitelist configuration option (#1489729)
RELEASE 1.0.0
-------------
diff --git a/config/defaults.inc.php b/config/defaults.inc.php
index 8c9b96f1a..2ff764fa1 100644
--- a/config/defaults.inc.php
+++ b/config/defaults.inc.php
@@ -358,6 +358,10 @@ $config['memcache_hosts'] = null; // e.g. array( 'localhost:11211', '192.168.1.1
// check client IP in session athorization
$config['ip_check'] = false;
+// List of trusted proxies
+// X_FORWARDED_* and X_REAL_IP headers are only accepted from these IPs
+$config['proxy_whitelist'] = array();
+
// check referer of incoming requests
$config['referer_check'] = false;
diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php
index ae3e3a414..c2009cee0 100644
--- a/program/lib/Roundcube/rcube_utils.php
+++ b/program/lib/Roundcube/rcube_utils.php
@@ -596,7 +596,9 @@ class rcube_utils
if (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') {
return true;
}
- if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') {
+ if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])
+ && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https'
+ && in_array($_SERVER['REMOTE_ADDR'], rcube::get_instance()->config->get('proxy_whitelist', array()))) {
return true;
}
if ($port && $_SERVER['SERVER_PORT'] == $port) {
@@ -681,13 +683,22 @@ class rcube_utils
*/
public static function remote_addr()
{
- if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
- $hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'], 2);
- return $hosts[0];
- }
+ // Check if any of the headers are set first to improve performance
+ if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']) || !empty($_SERVER['HTTP_X_REAL_IP'])) {
+ $proxy_whitelist = rcube::get_instance()->config->get('proxy_whitelist', array());
+ if (in_array($_SERVER['REMOTE_ADDR'], $proxy_whitelist)) {
+ if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+ foreach(array_reverse(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])) as $forwarded_ip) {
+ if (!in_array($forwarded_ip, $proxy_whitelist)) {
+ return $forwarded_ip;
+ }
+ }
+ }
- if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
- return $_SERVER['HTTP_X_REAL_IP'];
+ if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
+ return $_SERVER['HTTP_X_REAL_IP'];
+ }
+ }
}
if (!empty($_SERVER['REMOTE_ADDR'])) {