summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Eckhofer <felix@eckhofer.com>2014-03-26 14:13:40 +0100
committerFelix Eckhofer <felix@eckhofer.com>2014-03-26 20:44:16 +0100
commitef721fc430fbb19da13060105577bf7605606b81 (patch)
tree39e9c72efb345dc513e27dbfec1a71a14bb3cc01
parent3fca238554c90c51e8bc694bc280e0c117958b85 (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.
-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 b78d4cdae..9ed5bab68 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
+- Add proxy_whitelist configuration option (#1489729)
- Added toolbar button to move message in message view
- Improve UI integration of ACL settings
- Drop support for PHP < 5.3.7
diff --git a/config/defaults.inc.php b/config/defaults.inc.php
index e9cc939cb..ffce8e76a 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 authorization
$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 46d53ac91..4a183bd79 100644
--- a/program/lib/Roundcube/rcube_utils.php
+++ b/program/lib/Roundcube/rcube_utils.php
@@ -598,7 +598,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) {
@@ -683,13 +685,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'])) {