diff options
author | Felix Eckhofer <felix@eckhofer.com> | 2014-03-26 14:13:40 +0100 |
---|---|---|
committer | Felix Eckhofer <felix@eckhofer.com> | 2014-03-26 20:44:16 +0100 |
commit | ef721fc430fbb19da13060105577bf7605606b81 (patch) | |
tree | 39e9c72efb345dc513e27dbfec1a71a14bb3cc01 /program | |
parent | 3fca238554c90c51e8bc694bc280e0c117958b85 (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.
Diffstat (limited to 'program')
-rw-r--r-- | program/lib/Roundcube/rcube_utils.php | 25 |
1 files changed, 18 insertions, 7 deletions
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'])) { |