diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index d2af44626cdc..72bd9f114367 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -769,8 +769,7 @@ public function getClientIps() $clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP]))); $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from - - $ip = $clientIps[0]; // Fallback to this when the client IP falls into the range of trusted proxies + $firstTrustedIp = null; // Eliminate all IPs from the forwarded IP chain which are trusted proxies foreach ($clientIps as $key => $clientIp) { @@ -779,13 +778,22 @@ public function getClientIps() $clientIps[$key] = $clientIp = $match[1]; } + if (!filter_var($clientIp, FILTER_VALIDATE_IP)) { + unset($clientIps[$key]); + } + if (IpUtils::checkIp($clientIp, self::$trustedProxies)) { unset($clientIps[$key]); + + // Fallback to this when the client IP falls into the range of trusted proxies + if (null === $firstTrustedIp) { + $firstTrustedIp = $clientIp; + } } } // Now the IP chain contains only untrusted proxies and the client IP - return $clientIps ? array_reverse($clientIps) : array($ip); + return $clientIps ? array_reverse($clientIps) : array($firstTrustedIp); } /** diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index e17953819bde..d601204231e9 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -863,6 +863,9 @@ public function testGetClientIpsProvider() // client IP with port array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88:12345, 127.0.0.1', array('127.0.0.1')), + + // invalid forwarded IP is ignored + array(array('88.88.88.88'), '127.0.0.1', 'unknown,88.88.88.88', array('127.0.0.1')), ); }