From 5506ee8f6601288a171f229bff88d38dcd6ebdf3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 11 Aug 2014 10:25:24 +0200 Subject: [PATCH] Fix potential DoS when parsing HOST --- .../Component/HttpFoundation/Request.php | 3 +- .../HttpFoundation/Tests/RequestTest.php | 39 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index d7053339bd..93767f4aad 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1147,7 +1147,8 @@ class Request // as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user) // check that it does not contain forbidden characters (see RFC 952 and RFC 2181) - if ($host && !preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host)) { + // use preg_replace() instead of preg_match() to prevent DoS attacks with long host names + if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) { throw new \UnexpectedValueException('Invalid Host "'.$host.'"'); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 688f3094b9..e0cc1dcfd0 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1594,6 +1594,45 @@ class RequestTest extends \PHPUnit_Framework_TestCase // reset request for following tests Request::setTrustedHosts(array()); } + + public function testVeryLongHost() + { + $host = 'a'.str_repeat('.a', 40000); + $start = microtime(true); + + $request = Request::create('/'); + $request->headers->set('host', $host); + $this->assertEquals($host, $request->getHost()); + $this->assertLessThan(1, microtime(true) - $start); + } + + /** + * @dataProvider getHostValidities + */ + public function testHostValidity($host, $isValid) + { + $request = Request::create('/'); + $request->headers->set('host', $host); + + if ($isValid) { + $this->assertSame($host, $request->getHost()); + } + } else { + $this->setExpectedException('UnexpectedValueException', 'Invalid Host'); + $request->getHost(); + } + } + + public function getHostValidities() + { + return array( + array('.a', false), + array('a..', false), + array('a.', true), + array("\xE9", false), + array('[::1]', true), + ); + } } class RequestContentProxy extends Request