From 751b12c12bdc0da3c1434bbf0de1a33677ddfc77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Sun, 29 Nov 2015 00:02:58 +0100 Subject: [PATCH] [Request] Ignore invalid IP addresses sent by proxies Fixes symfony/symfony#15525 --- src/Symfony/Component/HttpFoundation/Request.php | 13 +++++++++++-- .../Component/HttpFoundation/Tests/RequestTest.php | 6 +++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index ff8d411a9c52e..3caccc2995289 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -814,7 +814,7 @@ public function getClientIps() } $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; foreach ($clientIps as $key => $clientIp) { // Remove port (unfortunately, it does happen) @@ -822,13 +822,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 f13f4791d93c2..4ad0c7c1819ca 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -858,7 +858,8 @@ public function testGetClientIpsForwardedProvider() // $expected $remoteAddr $httpForwarded $trustedProxies return array( array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', null), - array(array('_gazonk'), '127.0.0.1', 'for="_gazonk"', array('127.0.0.1')), + array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', array('127.0.0.1')), + array(array('88.88.88.88'), '127.0.0.1', 'for="unknown" for=88.88.88.88', array('127.0.0.1')), array(array('88.88.88.88'), '127.0.0.1', 'for="88.88.88.88:80"', array('127.0.0.1')), array(array('192.0.2.60'), '::1', 'for=192.0.2.60;proto=http;by=203.0.113.43', array('::1')), array(array('2620:0:1cfe:face:b00c::3', '192.0.2.43'), '::1', 'for=192.0.2.43, for=2620:0:1cfe:face:b00c::3', array('::1')), @@ -914,6 +915,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')), ); }