8000 Merge branch '2.0' into 2.1 · symfony/symfony@31f0efd · GitHub
[go: up one dir, main page]

Skip to content

Commit 31f0efd

Browse files
committed
Merge branch '2.0' into 2.1
* 2.0: added trusted hosts check Conflicts: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
2 parents 5129d3f + c35cc5b commit 31f0efd

File tree

6 files changed

+104
-7
lines changed

6 files changed

+104
-7
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ public function getConfigTreeBuilder()
7878
->scalarNode('ide')->defaultNull()->end()
7979
->booleanNode('test')->end()
8080
->scalarNode('default_locale')->defaultValue('en')->end()
81+
->arrayNode('trusted_hosts')
82+
->beforeNormalization()
83+
->ifTrue(function($v) { return is_string($v); })
84+
->then(function($v) { return array($v); })
85+
->end()
86+
->prototype('scalar')->end()
87+
->end()
8188
->end()
8289
;
8390

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public function load(array $configs, ContainerBuilder $container)
6262
$container->setParameter('kernel.secret', $config['secret']);
6363

6464
$container->setParameter('kernel.trusted_proxies', $config['trusted_proxies']);
65+
$container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']);
6566

6667
// @deprecated, to be removed in 2.3
6768
$container->setParameter('kernel.trust_proxy_headers', $config['trust_proxy_headers']);

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ public function boot()
4545
} elseif ($this->container->getParameter('kernel.trust_proxy_headers')) {
4646
Request::trustProxyData(); // @deprecated, to be removed in 2.3
4747
}
48+
49+
if ($trustedHosts = $this->container->getParameter('kernel.trusted_hosts')) {
50+
Request::setTrustedHosts($trustedHosts);
51+
}
4852
}
4953

5054
public function build(ContainerBuilder $container)

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public function testConfigTree($options, $results)
3131
public function getTestConfigTreeData()
3232
{
3333
return array(
34-
array(array('secret' => 's3cr3t'), array('secret' => 's3cr3t', 'trusted_proxies' => array(), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
34+
array(array('secret' => 's3cr3t'), array('secret' => 's3cr3t', 'trusted_proxies' => array(), 'trusted_hosts' => array(), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
3535
);
3636
}
3737

@@ -50,12 +50,12 @@ public function testValidTrustedProxies($options, $results)
5050
public function getTestValidTrustedProxiesData()
5151
{
5252
return array(
53-
array(array('secret' => 's3cr3t', 'trusted_proxies' => array('127.0.0.1')), array('secret' => 's3cr3t', 'trusted_proxies' => array('127.0.0.1'), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
54-
array(array('secret' => 's3cr3t', 'trusted_proxies' => array('::1')), array('secret' => 's3cr3t', 'trusted_proxies' => array('::1'), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
55-
array(array('secret' => 's3cr3t', 'trusted_proxies' => array('127.0.0.1', '::1')), array('secret' => 's3cr3t', 'trusted_proxies' => array('127.0.0.1', '::1'), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
56-
array(array('secret' => 's3cr3t', 'trusted_proxies' => null), array('secret' => 's3cr3t', 'trusted_proxies' => array(), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
57-
array(array('secret' => 's3cr3t', 'trusted_proxies' => false), array('secret' => 's3cr3t', 'trusted_proxies' => array(), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
58-
array(array('secret' => 's3cr3t', 'trusted_proxies' => array()), array('secret' => 's3cr3t', 'trusted_proxies' => array(), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
53+
array(array('secret' => 's3cr3t', 'trusted_proxies' => array('127.0.0.1')), array('secret' => 's3cr3t', 'trusted_hosts' => array(), 'trusted_proxies' => array('127.0.0.1'), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
54+
array(array('secret' => 's3cr3t', 'trusted_proxies' => array('::1')), array('secret' => 's3cr3t', 'trusted_hosts' => array(), 'trusted_proxies' => array('::1'), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
55+
array(array('secret' => 's3cr3t', 'trusted_proxies' => array('127.0.0.1', '::1')), array('secret' => 's3cr3t', 'trusted_hosts' => array(), 'trusted_proxies' => array('127.0.0.1', '::1'), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
56+
array(array('secret' => 's3cr3t', 'trusted_proxies' => null), array('secret' => 's3cr3t', 'trusted_hosts' => array(), 'trusted_proxies' => array(), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
57+
array(array('secret' => 's3cr3t', 'trusted_proxies' => false), array('secret' => 's3cr3t', 'trusted_hosts' => array(), 'trusted_proxies' => array(), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
58+
array(array('secret' => 's3cr3t', 'trusted_proxies' => array()), array('secret' => 's3cr3t', 'trusted_hosts' => array(), 'trusted_proxies' => array(), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => false), 'default_locale' => 'en', 'charset' => null)),
5959
);
6060
}
6161

src/Symfony/Component/HttpFoundation/Request.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ class Request
3939

4040
protected static $trustedProxies = array();
4141

42+
/**
43+
* @var string[]
44+
*/
45+
protected static $trustedHostPatterns = array();
46+
47+
/**
48+
* @var string[]
49+
*/
50+
protected static $trustedHosts = array();
51+
4252
/**
4353
* Names for headers that can be trusted when
4454
* using trusted proxies.
@@ -482,6 +492,32 @@ public static function setTrustedProxies(array $proxies)
482492
self::$trustProxy = $proxies ? true : false;
483493
}
484494

495+
/**
496+
* Sets a list of trusted host patterns.
497+
*
498+
* You should only list the hosts you manage using regexs.
499+
*
500+
* @param array $hostPatterns A list of trusted host patterns
501+
*/
502+
public static function setTrustedHosts(array $hostPatterns)
503+
{
504+
self::$trustedHostPatterns = array_map(function ($hostPattern) {
505+
return sprintf('{%s}i', str_replace('}', '\\}', $hostPattern));
506+
}, $hostPatterns);
507+
// we need to reset trusted hosts on trusted host patterns change
508+
self::$trustedHosts = array();
509+
}
510+
511+
/**
512+
* Gets the list of trusted host patterns.
513+
*
514+
* @return array An array of trusted host patterns.
515+
*/
516+
public static function getTrustedHosts()
517+
{
518+
return self::$trustedHostPatterns;
519+
}
520+
485521
/**
486522
* Sets the name for trusted headers.
487523
*
@@ -1007,6 +1043,24 @@ public function getHost()
10071043
throw new \UnexpectedValueException('Invalid Host');
10081044
}
10091045

1046+
if (count(self::$trustedHostPatterns) > 0) {
1047+
// to avoid host header injection attacks, you should provide a list of trusted host patterns
1048+
1049+
if (in_array($host, self::$trustedHosts)) {
1050+
return $host;
1051+
}
1052+
1053+
foreach (self::$trustedHostPatterns as $pattern) {
1054+
if (preg_match($pattern, $host)) {
1055+
self::$trustedHosts[] = $host;
1056+
1057+
return $host;
1058+
}
1059+
}
1060+
1061+
throw new \UnexpectedValueException('Untrusted Host');
1062+
}
1063+
10101064
return $host;
10111065
}
10121066

src/Symfony/Component/HttpFoundation/Tests/RequestTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,37 @@ public function iisRequestUriProvider()
13581358
)
13591359
);
13601360
}
1361+
1362+
public function testTrustedHosts()
1363+
{
1364+
// create a request
1365+
$request = Request::create('/');
1366+
1367+
// no trusted host set -> no host check
1368+
$request->headers->set('host', 'evil.com');
1369+
$this->assertEquals('evil.com', $request->getHost());
1370+
1371+
// add a trusted domain and all its subdomains
1372+
Request::setTrustedHosts(array('.*\.?trusted.com$'));
1373+
1374+
// untrusted host
1375+
$request->headers->set('host', 'evil.com');
1376+
try {
1377+
$request->getHost();
1378+
$this->fail('Request::getHost() should throw an exception when host is not trusted.');
1379+
} catch (\UnexpectedValueException $e) {
1380+
$this->assertEquals('Untrusted Host', $e->getMessage());
1381+
}
1382+
1383+
// trusted hosts
1384+
$request->headers->set('host', 'trusted.com');
1385+
$this->assertEquals('trusted.com', $request->getHost());
1386+
$request->headers->set('host', 'subdomain.trusted.com');
1387+
$this->assertEquals('subdomain.trusted.com', $request->getHost());
1388+
1389+
// reset request for following tests
1390+
Request::setTrustedHosts(array());
1391+
}
13611392
}
13621393

13631394
class RequestContentProxy extends Request

0 commit comments

Comments
 (0)
0