From c3819abbf2c9571069c893d27ae6170bda413925 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 29 Nov 2012 10:09:19 +0100 Subject: [PATCH] Fix handling of proxy addresses - Never use Client-IP header; untrustworthy - When multiple addresses are present in X-Forwaded-For header, use the rightmost, not leftmost. See: http://en.wikipedia.org/wiki/X-Forwarded-For#Format --- library/Zend/Session/Validator/RemoteAddr.php | 10 +++------- .../Session/Validator/RemoteAddrTest.php | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/library/Zend/Session/Validator/RemoteAddr.php b/library/Zend/Session/Validator/RemoteAddr.php index 10ac63de488..ade6af4d5ff 100644 --- a/library/Zend/Session/Validator/RemoteAddr.php +++ b/library/Zend/Session/Validator/RemoteAddr.php @@ -94,15 +94,11 @@ protected function getIpAddress() { if (static::$useProxy) { // proxy IP address - if (isset($_SERVER['HTTP_CLIENT_IP']) && $_SERVER['HTTP_CLIENT_IP']) { - $ips = explode(',', $_SERVER['HTTP_CLIENT_IP']); - return trim($ips[0]); - } - - // proxy IP address + // Only ever look at X-Forwarded-For header; Client-IP is unreliable if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR']) { $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); - return trim($ips[0]); + $ip = array_pop($ips); + return trim($ip); } } diff --git a/tests/ZendTest/Session/Validator/RemoteAddrTest.php b/tests/ZendTest/Session/Validator/RemoteAddrTest.php index 020e2c0bbec..71a72999eca 100644 --- a/tests/ZendTest/Session/Validator/RemoteAddrTest.php +++ b/tests/ZendTest/Session/Validator/RemoteAddrTest.php @@ -102,7 +102,7 @@ public function testHttpClientIp() $this->restore(); } - public function testMultipleHttpXForwardedFor() + public function testUsesRightMostAddressWhenMultipleHttpXForwardedForAddressesPresent() { $this->backup(); $_SERVER['REMOTE_ADDR'] = '0.1.2.3'; @@ -110,7 +110,20 @@ public function testMultipleHttpXForwardedFor() RemoteAddr::setUseProxy(true); $validator = new RemoteAddr(); RemoteAddr::setUseProxy(false); - $this->assertEquals('2.1.2.3', $validator->getData()); + $this->assertEquals('1.1.2.3', $validator->getData()); + $this->restore(); + } + + public function testShouldNotUseClientIpHeaderToTestProxyCapabilities() + { + $this->backup(); + $_SERVER['REMOTE_ADDR'] = '0.1.2.3'; + $_SERVER['HTTP_X_FORWARDED_FOR'] = '2.1.2.3, 1.1.2.3'; + $_SERVER['HTTP_CLIENT_IP'] = '0.1.2.4'; + RemoteAddr::setUseProxy(true); + $validator = new RemoteAddr(); + RemoteAddr::setUseProxy(false); + $this->assertEquals('1.1.2.3', $validator->getData()); $this->restore(); } }