-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Added the documentation for the trusted_hosts option #3876
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ Configuration | |
* `http_method_override`_ | ||
* `ide`_ | ||
* `test`_ | ||
* `trusted_hosts`_ | ||
* `trusted_proxies`_ | ||
* `form`_ | ||
* enabled | ||
|
@@ -114,6 +115,69 @@ services related to testing your application (e.g. ``test.client``) are loaded. | |
This setting should be present in your ``test`` environment (usually via | ||
``app/config/config_test.yml``). For more information, see :doc:`/book/testing`. | ||
|
||
.. _reference-framework-trusted-hosts: | ||
|
||
trusted_hosts | ||
~~~~~~~~~~~~~ | ||
|
||
**type**: ``array`` | ||
|
||
The value of the ``$_SERVER['HOST']`` parameter cannot be safely trusted because | ||
users can manipulate it. This option whitelists the hosts that your Symfony | ||
application can respond to. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you mean by "can respond to"? It sounds like the app will not work unless you put your domain name here. I don't think this is what we mean - I actually don't know what this feature does tbh :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To understand the feature, it's better to see the code: 1. When booting, FrameworkBundle sets the trusted hosts of the Request: class FrameworkBundle extends Bundle
{
public function boot()
{
// ...
if ($trustedHosts = $this->container->getParameter('kernel.trusted_hosts')) {
Request::setTrustedHosts($trustedHosts);
}
}
// ...
} 2. The Request uses this configuration value to define the trusted hosts 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();
} 3. When dealing with the Request, one of the called methods is protected function prepareRequestUri()
{
$requestUri = '';
if ($this->headers->has('X_ORIGINAL_URL')) {
// ...
} elseif ($this->headers->has('X_REWRITE_URL')) {
// ...
} elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') {
// ...
} elseif ($this->server->has('REQUEST_URI')) {
$requestUri = $this->server->get('REQUEST_URI');
// HTTP proxy reqs setup request URI with scheme and host
// [and port] + the URL path, only use URL path
$schemeAndHttpHost = $this->getSchemeAndHttpHost();
if (strpos($requestUri, $schemeAndHttpHost) === 0) {
$requestUri = substr($requestUri, strlen($schemeAndHttpHost));
}
} elseif ($this->server->has('ORIG_PATH_INFO')) {
// ...
}
// normalize the request URI to ease creating sub-requests from this request
$this->server->set('REQUEST_URI', $requestUri);
return $requestUri;
} 4. Indirectly, the public function getHost()
{
// ...
// 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)) {
throw new \UnexpectedValueException(sprintf('Invalid Host "%s"', $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(sprintf('Untrusted Host "%s"', $host));
}
return $host;
} So, if you leave this option blank, everything works as previously did. If you set any value, the application will thro an exception if the host provided by the user request doesn't match the configured regular expressions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, so the purpose of the feature is so that I can "restrict my application to respond to only a sub-set of hosts". Is that accurate? What exactly is the security risk? Or said differently, why would a developer care about this? I would like to re-word the first few sentences to address the use-case. This is totally invented (since I don't know the real use-case), but for example:
That's weak wording... but you get the idea. I'm purposefully being "dumb" (and not looking up more detailson) so that if I understand this feature, then we're good :). Thanks! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ping @javiereguiluz! |
||
|
||
.. configuration-block:: | ||
|
||
.. code-block:: yaml | ||
|
||
framework: | ||
trusted_hosts: ['acme.com', 'acme.org'] | ||
|
||
.. code-block:: xml | ||
|
||
<framework:config trusted-hosts="acme.com, acme.org"> | ||
<!-- ... --> | ||
</framework> | ||
|
||
.. code-block:: php | ||
|
||
$container->loadFromExtension('framework', array( | ||
'trusted_hosts' => array('acme.com', 'acme.org'), | ||
)); | ||
|
||
Hosts can also be configured using regular expressions, which make it easier to | ||
respond to any subdomain: | ||
|
||
.. configuration-block:: | ||
|
||
.. code-block:: yaml | ||
|
||
framework: | ||
trusted_hosts: ['.*\.?acme.com$', '.*\.?acme.org$'] | ||
|
||
.. code-block:: xml | ||
|
||
<framework:config trusted-hosts=".*\.?acme.com$, .*\.?acme.org$"> | ||
<!-- ... --> | ||
</framework> | ||
|
||
.. code-block:: php | ||
|
||
$container->loadFromExtension('framework', array( | ||
'trusted_hosts' => array('.*\.?acme.com$', '.*\.?acme.org$'), | ||
)); | ||
|
||
In addition, you can also set the trusted hosts in the front controller using | ||
the ``Request::setTrustedHosts()`` method: | ||
|
||
.. code-block:: php | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use the |
||
|
||
// web/app.php | ||
Request::setTrustedHosts(array('.*\.?acme.com$', '.*\.?acme.org$')); | ||
|
||
The default value for this option is an empty array, meaning that the application | ||
can respond to any given host. | ||
|
||
.. _reference-framework-trusted-proxies: | ||
|
||
trusted_proxies | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why did you add this? Did you want to add a link to this section, but you forgot to commit that link?