Merge branch '2.1' into 2.2

* 2.1:
  added trusted hosts check

Conflicts:
	src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
	src/Symfony/Component/HttpFoundation/Request.php
This commit is contained in:
Fabien Potencier 2013-08-07 16:00:53 +02:00
commit b8b972fe74
6 changed files with 98 additions and 1 deletions

View File

@ -68,6 +68,13 @@ class Configuration implements ConfigurationInterface
->scalarNode('ide')->defaultNull()->end()
->booleanNode('test')->end()
->scalarNode('default_locale')->defaultValue('en')->end()
->arrayNode('trusted_hosts')
->beforeNormalization()
->ifTrue(function($v) { return is_string($v); })
->then(function($v) { return array($v); })
->end()
->prototype('scalar')->end()
->end()
->end()
;

View File

@ -67,6 +67,7 @@ class FrameworkExtension extends Extension
}
$container->setParameter('kernel.trusted_proxies', $config['trusted_proxies']);
$container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']);
// @deprecated, to be removed in 2.3
$container->setParameter('kernel.trust_proxy_headers', $config['trust_proxy_headers']);

View File

@ -46,6 +46,10 @@ class FrameworkBundle extends Bundle
} elseif ($this->container->getParameter('kernel.trust_proxy_headers')) {
Request::trustProxyData(); // @deprecated, to be removed in 2.3
}
if ($trustedHosts = $this->container->getParameter('kernel.trusted_hosts')) {
Request::setTrustedHosts($trustedHosts);
}
}
public function build(ContainerBuilder $container)

View File

@ -22,7 +22,7 @@ class ConfigurationTest extends \PHPUnit_Framework_TestCase
$config = $processor->processConfiguration(new Configuration(), array(array('secret' => 's3cr3t')));
$this->assertEquals(
array_merge(array('secret' => 's3cr3t'), self::getBundleDefaultConfig()),
array_merge(array('secret' => 's3cr3t', 'trusted_hosts' => array()), self::getBundleDefaultConfig()),
$config
);
}

View File

@ -39,6 +39,16 @@ class Request
protected static $trustedProxies = array();
/**
* @var string[]
*/
protected static $trustedHostPatterns = array();
/**
* @var string[]
*/
protected static $trustedHosts = array();
/**
* Names for headers that can be trusted when
* using trusted proxies.
@ -501,6 +511,32 @@ class Request
return self::$trustedProxies;
}
/**
* Sets a list of trusted host patterns.
*
* You should only list the hosts you manage using regexs.
*
* @param array $hostPatterns A list of trusted host patterns
*/
public static function setTrustedHosts(array $hostPatterns)
{
self::$trustedHostPatterns = array_map(function ($hostPattern) {
return sprintf('{%s}i', str_replace('}', '\\}', $hostPattern));
}, $hostPatterns);
// we need to reset trusted hosts on trusted host patterns change
self::$trustedHosts = array();
}
/**
* Gets the list of trusted host patterns.
*
* @return array An array of trusted host patterns.
*/
public static function getTrustedHosts()
{
return self::$trustedHostPatterns;
}
/**
* Sets the name for trusted headers.
*
@ -1050,6 +1086,24 @@ class Request
throw new \UnexpectedValueException('Invalid Host');
}
if (count(self::$trustedHostPatterns) > 0) {
// to avoid host header injection attacks, you should provide a list of trusted host patterns
if (in_array($host, self::$trustedHosts)) {
return $host;
}
foreach (self::$trustedHostPatterns as $pattern) {
if (preg_match($pattern, $host)) {
self::$trustedHosts[] = $host;
return $host;
}
}
throw new \UnexpectedValueException('Untrusted Host');
}
return $host;
}

View File

@ -1515,6 +1515,37 @@ class RequestTest extends \PHPUnit_Framework_TestCase
)
);
}
public function testTrustedHosts()
{
// create a request
$request = Request::create('/');
// no trusted host set -> no host check
$request->headers->set('host', 'evil.com');
$this->assertEquals('evil.com', $request->getHost());
// add a trusted domain and all its subdomains
Request::setTrustedHosts(array('.*\.?trusted.com$'));
// untrusted host
$request->headers->set('host', 'evil.com');
try {
$request->getHost();
$this->fail('Request::getHost() should throw an exception when host is not trusted.');
} catch (\UnexpectedValueException $e) {
$this->assertEquals('Untrusted Host', $e->getMessage());
}
// trusted hosts
$request->headers->set('host', 'trusted.com');
$this->assertEquals('trusted.com', $request->getHost());
$request->headers->set('host', 'subdomain.trusted.com');
$this->assertEquals('subdomain.trusted.com', $request->getHost());
// reset request for following tests
Request::setTrustedHosts(array());
}
}
class RequestContentProxy extends Request