Hi,
I cache some menu links in my application (datacaching using filecache), sometimes hostname part of these links change to a random website (usually chinese websites) and I have to flush the cache to make it work again.
after some research and studying webserver logs it turned out to be "Host Header Attack". turning off caching would solve the problem but that's not the solution for me as I have very high traffic websites. reading some articles ( https://www.acunetix.com/vulnerabilities/web/host-header-attack ) suggest not using $_SERVER['HTTP_HOST']
when creating links and using $_SERVER['SERVER_NAME']
instead. I tried to simulate the situation using burp suite application and the suggested solution acutally works. but the code responsible for getting host info is located in core framework and is in \yii\web\Request::getHostInfo
method and the above change should be applied on that method.
although I don't know if it has any other side effect rather than ruined links when caching is enabled.
@tom-- , what's your view on this risk?
Test file:
<?php
echo $_SERVER['HTTP_HOST'];
echo "\n";
Test cURL request:
curl -v -H "Host: fake.com" -X GET http://example.com/test.php
* About to connect() to example.com port 80 (#0)
* Trying 195.177.208.33... connected
* Connected to example.com (195.177.208.33) port 80 (#0)
> GET /test.php HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Accept: */*
> Host: fake.com
>
< HTTP/1.1 404 Not Found
< Server: nginx/1.10.0
< Date: Mon, 21 Nov 2016 13:54:59 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
<
No input file specified.
* Connection #0 to host example.com left intact
* Closing connection #0
It seems that overriding $_SEVER['HTTP_HOST']
via custom header is not allowed.
@klimov-paul What's your point?
As for accessing particular server via invalid hostname provided via hosts
file - it should be covered at the hosting settings. For example usually we deny access to the server by direct IP, e.g. http://10.10.10.15
will show 404 even while example.com
is resolved as 10.10.10.15
.
This issue should be resolved by sever configuration.
I agree that apps should not rely on Host header. In general it would be used by the web server and of no interest to the web app.
I am not comfortable with the advice to use SERVER_NAME instead. I prefer to use a combination of web server and application config.
It is unlikely this issue can be solved at Yii side as using $_SERVER['SERVER_NAME']
is not reliable. It does not always contain a host name.
Besides keep in mind necessity of trakcing down sub domains.
@sepidemahmoodi can you provide more details about your sever setup, do you use nginx or apache, how is php set up? fcgi or mod_php or something else?
Two questions I don't understand:
You can configure Request::hostInfo
in your application config to be hardcoded:
return [
'components' => [
'request' => [
'hostInfo' => 'http://example.com'
],
],
];
Also you can unset $_SERVER['HOST_NAME']
during application configuration or bootstrap:
unset($_SERVER['HOST_NAME']);
return [/* application config */];
This will cause Request
to use $_SERVER['SERVER_NAME']
.
As far as I see, this vulnerability should be resolved at WebServer configuration (e.g. Apache or Nginx)
@klimov-paul I agree but I am not satisfied that answer resolves this issue.
I do not know. At the present state - I can see no way such issue can be solved at Yii side.
Unless to hardcode domain name somewhere there is no fix for it.
My opinion - this is a common WebServer setup knowledge.
Unless you explicitly specificly catch all
at your Web Server, this issue can not appear.
See Apache and Nginx docs:
http://httpd.apache.org/docs/trunk/vhosts/examples.html#defaultallports
https://www.nginx.com/resources/wiki/start/topics/examples/server_blocks/
$ php -S 0.0.0.0:8000 -r 'echo $_SERVER["HTTP_HOST"];' &
$ curl -v -H "Host: fake.ru" http://127.0.0.1:8000/
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
> Host: fake.ru
> User-Agent: curl/7.49.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Host: fake.ru
< Connection: close
< X-Powered-By: PHP/7.0.12
< Content-type: text/html; charset=UTF-8
<
fake.ru
* Closing connection 0
I would prefer if the framework's defaults are robust against such improper configuration. The h1 on yiiframework.com says "The Fast, Secure and Professional PHP Framework". If there is an opportunity to mitigate this risk, we should take it.
Request::getHostInfo()
uses Host by defaultBaseUrl::to()
, base()
and home()
use Request::getHostInfo()
UrlManager
and UrlRule
use Request::getHostInfo()
and ::to()
While Request::getHostInfo()
is quite well documented, it could additionally warn that Host header cannot be trusted, using it to generate links is unnecessary, and it's wise to configure the value instead.
But I would prefer if Yii would not use the Host header unless the user configures it, and document this configuration with the warning.
I'll think about how this might be achieved and return to this discussion later.
I can't reproduce this risk on my servers, but your example shows that it can occur depending on your server setup. I agree to hard-code
the domain in the application config, not for the least to be consistent with our core values and to extend our security section.
According to the docs http://php.net/reserved.variables.server $_SERVER['SERVER_NAME']
can be spoofed on Apache2 with a certain config option turned off.
@dynasource a typical server config strictly maps one vhost to one entry script and does not allow the default host access to php apps. I think @klimov-paul and I also regard as correct. And in this case there is no reason to use the value of the Host header.
Trouble can arise if the server forwards everything or a default domain to an entry script. But in this case it is not safe to use the Host header.
Related: #10854
While both are improvements, I am not really satisfied with changing from HTTP_HOST header to SERVER_NAME or a white-list.
I'd like to have a hostName app config property (not sure of what) that is null by default and can be a string or a callable. If it is null on read in Request::getHostInfo()
, throw an exception.
Thinks I like about this:
How is Yii Framework involved in this vulnerability?
It is not. That's server config issue.
What, if anything, could the framework do to help users avoid pitfalls like that @sepidemahmoodi reported?
Nothing. It's server config issue.
Does anything in Yii (including demo apps) encourage or facilitate users to make this mistake?
No.
Can Yii do anything different to help users avoid the risk?
@tom--, i have checked the host header mock at my stage environment, which has a proper vhost
configuration. Such attack has no effect on it:
curl -v -H "Host: fake.ru" http://my.stage.com/test.php
* About to connect() to my.stage.com port 80 (#0)
* Trying 5.9.17.198... connected
* Connected to my.stage.com (5.9.17.198) port 80 (#0)
> GET /test.php HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Accept: */*
> Host: fake.ru
>
< HTTP/1.1 404 Not Found
< Date: Tue, 22 Nov 2016 12:35:05 GMT
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
<
File not found.
* Closing connection #0
For comparison: normal request:
curl -v http://my.stage.com/test.php
* About to connect() to my.stage.com port 80 (#0)
* Trying 5.9.17.198... connected
* Connected to my.stage.com (5.9.17.198) port 80 (#0)
> GET /test.php HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Host: my.stage.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 22 Nov 2016 12:37:33 GMT
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
<
my.stage.com
* Closing connection #0
With the correct server virtual hosts configuration - this issue can not appear.
@klimov-paul you're right. Such issue may appear only if you've configured your host as wildcard or used IP.
Can Yii do anything different to help users avoid the risk?
We can create a filter (yii\base\ActionFilter
) which will check host name againts some hosts white list or wildcard, e.g. *.example.com
. Filters can be applied not only at controller level, but at module level as well, and thus at application level.
Another possible implementation can be using yii\base\BootstrapInterface
.
But I would prefer if Yii would not use the Host header unless the user configures it, and document this configuration with the warning.
As I already said SERVER_NAME
may not hold a host name. Also in case you are running sub-domains, e.g. en.example.com
, ru.example.com
, fr.example.com
and so on - SERVER_NAME
can not be used to fetch out subdomain.
config issue
Well yes, same for things like IP forwarding from reverse proxies (ideally the webserver is mapping IP to REMOTE_ADDR based on webserver config), still other frameworks like symfony have app-support for it too.
@rob006 already mentioned #10854 and I still think adopting a symfony-like solution is the proper solution.
Yes, a whitelist with patterns would do. I don't think it's possible to introduce without breaking compatibility though.
I don't think it's possible to introduce without breaking compatibility though.
Why? If white-list is equal to null
check can be skipped, keeping a BC.
The only question is where the check shold be performed.
Right. The check should be performed as early as possible.
I completely agree that we can blame server config.
This means Yii takes the stance that a the server must enforce the 1:1 mapping of Hose header to vhost to app.
So why then does Yii use HTTP_HOST?
@klimov-paul I agree with you (and now for the third time) that a correctly configured web server eliminates this vulnerability.
Instead of a white-list, I proposed yesterday a user-provided callable that returns a host name. More flexibility for the user.
Instead of a white-list, I proposed yesterday a user-provided callable that returns a host name. More flexibility for the user.
Disagreed.
First of all, same web application may actually respond to several different host names. Such use case is rare, but still occurs from time to time.
Also, do not forgert about sub-domains - host name whlie-list should allow pattern (wildcard) specification.
There are projects with sub-domains. For example, slack does it this way with <subdomain>.slack.com
. In this case the domain is actually used and checked. It's part of the domain model and a valid use case.
The user can put a white-list in the callable, if that's needed, or any other function for deriving a host name. A white-list of HTTP_HOST values is just one function to derive a host name from environment.
@tom-- am I correct that you're proposing callback that's getting host and returns true/false?
no. the callback returns the value that Request uses for host name.
it can access the Request object as $this, the app through the singleton and superglobals
Actual determine of the white-list value is a details.
The main question is where we should put this functionality into?
ActionFilter
BootstrapInterface
Request
or Application
return [
'components' => [
'request' => [
'hostInfo' => <something>
],
],
];
in the above, the user can configure hostInfo to be
No, this would not work for sub-domains.
@klimov-paul it's a tricky question.
Security-wise the issue is mostly about 1st case. In 2nd case it's likely solved in domain layer of the application.
Should be a filter then.
There can be 1 entry point for mutiple domains. I have a platform Saas wich has roughly 100 domains pointed towards the same entry point. Each with an own VHost(nginx)
For me whitelisting would make things very complicated.
PR with filter implementation: #13063
I'm for adding this to the core. I think we should not completely rely on server config and limit prevention of HTTP Host header attacks to configuring server.
For example Django's approach is separate setting ALLOWED_HOSTS.
This is a security measure to prevent HTTP Host header attacks, which are possible even under many seemingly-safe web server configurations.
This related section also can be useful - Host Header Validation.
Warning
Previous versions of this document recommended configuring your web server to ensure it validates incoming HTTP Host headers. While this is still recommended, in many common web servers a configuration that seems to validate the Host header may not in fact do so. For instance, even if Apache is configured such that your Django site is served from a non-default virtual host with the ServerName set, it is still possible for an HTTP request to match this virtual host and supply a fake Host header. Thus, Django now requires that you set ALLOWED_HOSTS explicitly rather than relying on web server configuration.
@arogachev thanks for references. These are useful for docs.
@samdark I don't like seeing it solved via action filter. Why not simply modify a property Yii::$app->request->trustedHosts = ['example.com'];
```php
public function setTrustedHosts(array $hosts)
{
$this->_trustedHosts = $hosts;
$this->_hostInfo = null; // Reset internal cache
}
````
As soon as you assign a new array, any access to Request::getHostInfo()
(e.g. on url creation) should then re-evaluate based on $this->_trustedHosts
...
Although in symfony it's a little more complex, for example they allow to set host regexes instead of simple strings, so you could set ['.*\.example.com']
: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L571
I don't like seeing it solved via action filter. Why not simply modify a property
See https://github.com/yiisoft/yii2/issues/13050#issuecomment-262253751 :
If it is an app with many sub-domains then it may make sense to configure it per action.
hey allow to set host regexes instead of simple strings
HostControl
at #13063 allows specification of hots name as wildcard, e.g. *.example.com
.
Your implementation makes sense. I forgot about the behavior implications. Should've looked more carefully at the PR.
馃憤
I'd prefer to add this as a property to the Request class which can be configured like it is done by symfony and django. something like trustedHosts
property.
related to #10854 #8746 #11534
agree with @cebe
I'd prefer to add this as a property to the Request class which can be configured like it is done by symfony and django. something like trustedHosts property.
Disagreed.
1) Request
class should not involve access control logic. We have created a filters for that.
2) There should be a posibility to setup your own 'invalid host' handler. For example: you may want to redirect user back to correct host instead of show error page. Adding this to Request
as well even more inconsistent.
3) Throwing single exception is NOT reliable. In general this will trigger regular Yii error page to appear. This page may as well contain an absolute URL links in main menu, which will be cached. In this way - no procetion is actually given.
4) Wrong host access in general should throw HttpException
with 404 to be consistent with the regular server-based vhost
processing. Throwning 500 error is inconsistent. While throwing 404 inside Request
is inconsistent too, as instance of this class can be used not only for processing the current request.
shouldt Request be the place where the developer overrides parameters which are otherwise resolved automatically?
It is already: you can set Request::$hostInfo
even how to hardcode host parameters to be used.
But this class should not perform access control logic.
Throwing single exception is NOT reliable. In general this will trigger regular Yii error page to appear. This page may as well contain an absolute URL links in main menu, which will be cached. In this way - no procetion is actually given.
This is because you allow Request
to use invalid hostname in app. If you validate $_SERVER['HTTP_HOST']
in getHostInfo()
there is no such problem - $_SERVER['HTTP_HOST']
is ignored, $_SERVER['SERVER_NAME']
is used and you probably don't need do anything else. This is much more reliable solution.
$_SERVER['HTTP_HOST'] is ignored, $_SERVER['SERVER_NAME'] is used
As I already said at least twice usage of $_SERVER['SERVER_NAME']
for the host name retrieving is not reliable. It may contain a wrong value.
$_SERVER['SERVER_NAME']
is no go because one app instance may handle many domains.
As I already said at least twice uasge of $_SERVER['SERVER_NAME'] for the host name retrieving is not reliable. It may contain a wrong value.
Define "wrong". Does $_SERVER['SERVER_NAME']
could be compromised by attacker?
@samdark What is wrong with using valid hostname for invalid request? Even if app handle multiple domains, $_SERVER['SERVER_NAME']
should contain one of them, so there is no risk of injecting invalid hostname to cache.
$_SERVER['SERVER_NAME']
is somethign configured at server side. It can contain random string. As well as it can contain something like *.example.com
, which is invalid domain name either.
Indeed in correctly configured web server it will contain the host name, but in correctly configured web server you will be unable to access application from invalid host.
@rob006 the use case is multi-domain app. One domain per user such as samdark.slack.com
, rob006.slack.com
. You can't configure server in advance so you're using wildcard or even catch all (IP) in case custom domain could be attached. In this case I'm not sure what will be in $_SERVER['SERVER_NAME']
.
and still in some way i think this issue isn't at all at Yii, but at the server configuration.
So why build in fail saves for something that is not the responsibility of Yii.
As well as it can contain something like *.example.com
Not true, at least for Apache:
root@robert-laptop:/etc/apache2/sites-enabled# apache2ctl -t
AH00526: Syntax error on line 10 of /etc/apache2/sites-enabled/000-default.conf:
Invalid ServerName "*.example.com" use ServerAlias to set multiple server names.
Action '-t' failed.
The Apache error log may have more information.
Also vhost which catch all request is still correctly configured server. It may be not secure enough, but it is default config for Ubuntu for example.
and still in some way i think this issue isn't at all at Yii, but at the server configuration.
So why build in fail saves for something that is not the responsibility of Yii.
Sometimes server configuration may be out of the developer reach.
Not true, at least for Apache:
There is also an Nginx, IIS, Zeus and so on.
We should emphasize that server config is the right place to fix it in the guide and apidoc of the filter and add the filter as a PHP solution if server config does not work.
There is also an Nginx, IIS, Zeus and so on.
So we should check if someone could intentionally break config of his webserver and protect against this?
@rob006, actually I would be happy if this issue could be resolved by just moving to $_SERVER['SERVER_NAME']
- but it can not. It is not that simple.
This is sad thing to realize, but it is as it is.
@klimov-paul If you don't trust $_SERVER['SERVER_NAME']
then validate it too. The point is, if Request::getHostInfo()
will return malformed hostname, that means that it is unreliable and broken by design. I'm not against ActionFilter itself, but hostname validation should be done the earliest as possible. And doing validation in Request::getHostInfo()
will simplify HostControll
filter into:
function() {
if (empty(Yii::$app->request->hostName)) {
Yii::$app->request->hostInfo = 'https://example.com'; // optional default host info used in 404 error page
throw new NotFoundHttpException('Invalid host name.');
}
};
hostname validation should be done the earliest as possible.
Setup filter at Application::beforeRequest()
level is exactly the earliest as possible
.
What is the problem?
And doing validation in Request::getHostInfo() will simplify HostControll filter into:
It can not. In case host name
is used at least once while rendering error page - you will see 500 error instead of 404, as it will throw new NotFoundHttpException
exception, while already processing exception.
Setup filter at Application::beforeRequest() level is exactly the earliest as possible.
What is the problem?
The problem is that Request::getHostInfo()
will return unsafe value. So I'm proposing to validate host info before it is returned by Request::getHostInfo()
(in beforeRequest
), you're proposing doing this after this. So my proposal is the earliest of the earliest as possible
. :)
It can not. In case host name is used at least once while rendering error page - you will see 500 error instead of 404, as it will throw new NotFoundHttpException exception, while alreay processing exception.
No? Request::getHostInfo()
will return null
if host info is invalid. This should not brake anything.
But still a faulty configuration is a problem that should be fixed elsewhere.
Request::getHostInfo()
will returnnull
if host info is invalid.
I do not like such behavior. For me cases host is invalid
and there is no host at all
are different.
I do not like to mix them up.
For example: request, even with invalid Host Name
, may still need to be logged for the error processing.
Just tell if host is invalid means there is no host at all does not feel to be right.
I do not like such behavior. For me cases host is invalid and there is no host at all are different.
I do not like to mix them up.
For example: request, even with invalid Host Name, may still need to be logged for the error processing.
We could add event for that case? Like onInvalidHostInfo
?
I can't really imagine usecase when you get empty hostInfo from valid request.
Also I was thinking about setting Request::$_hostInfo
to empty string or false
if it was invalid.
We could add event for that case? Like onInvalidHostInfo?
How it will be different from current state?
I can't really imagine usecase when you get empty hostInfo from valid request.
At the present state following condition:
if (Yii::$app->request->getHostInfo() === null)
indicates there is no host information available at all.
Such thing may happen while running console application.
Alhough such condition is unlikely to be used for some business logic - it may still appear.
Also I was thinking about setting
Request::$_hostInfo
to empty string or false if it was invalid.
Returning empty host info
will produce invalid absolute URLs in silent mode.
This may confuse the developer at some stage, while his project is moving from one domain name to another one.
If 'host name' check fails - it should produce an explicit error - otherwise it makes no sense.
How it will be different from current state?
You will be able to log this event and throw exception if you want. Or set hostInfo to valid value and continue request. This is developer choice.
Returning empty host info will produce invalid absolute URLs in silent mode.
Thats why this should be documented. Hostname filtering will be disabled by default anyway.
@rob006 documenting it isn't enough. Failing fast is the right way in case of security matters and Paul's solution makes app fail before any processing occurs.
See the original issue description: usage of cache for HTML fragment containing an absolute URL.
In case Request::getHostInfo()
returns null
or false
program will produce following URL for login page:
http:///site/login
Although this is better then substituted host name:
http://fake.com/site/login
I can not consider such approach as a solution for the problem.
documenting it isn't enough. Failing fast is the right way in case of security matters and Paul's solution makes app fail before any processing occurs.
It fails after Request::$hostInfo
is set to invalid value. If you want fail so much - so be it, but using malformed hostInfo in further processing is unacceptable IMO.
@klimov-paul I'm sure you can imagine solution to prevent cerating URLs like http:///site/login
.
I'm sure you can imagine solution to prevent cerating URLs like http:///site/login.
I can not.
Since you are insisting on returning empty host info - you should provide one.
Since you are insisting on returning empty host info - you should provide one.
In console app you already have empty host info and I never seen such URLs, so I guess that this problem doesn't even exist.
But I can create alternative PR with Symfony-way solution, just give me few days.
In console app you already have empty host info and I never seen such URLs, so I guess that this problem doesn't even exist.
In console Application you may still need to create a URLs. For example, while sending some notification emails. However, developer expects having problem, while generating URLs in console application and will definitely verify the results.
However, having trusted hosts
configured at application config, you can easily forget about in case project domain name changing. Thus you will have invalid URLs created.
Same will happen, if you cache main menu and get substituted 'host header' just in time this cache created.
But I can create alternative PR with Symfony-way solution, just give me few days.
Do not ask me. I have make my decision on this matter.
Symfony has another style of application flow and data verification. Thus I can not accept some solution, just because Symfony does this in this way
.
I would prefer to close this issue already. Thus your efforts may be in vain at the end.
Unless other team members are willing to wait, there is no need to proceed.
However, having trusted hosts configured at application config, you can easily forget about in case project domain name changing.
So you assume that people will forget to change this in trusted host configuration, but will remember about this in console config?
I would rather assume that they will forget that Request::$hostInfo
is insecure, so they can't use it in error handling.
Thus you will have invalid URLs created.
You will get relative URL instead of absolute. It is far better than having invalid host in URL.
no matter what point u look at it, its a server configuration fault, wich shouldnt be solved in YII,
as proposed above we can have a filter wich does an additional check,
Imo thats the best we can do, i mean there can be many more problems when the server isnt configured right.
I think the best solution would be to merge @klimov-paul pull request which handles both PHP way of solving the issue and advertising having your server set up properly in the docs.
It doesn't make sense to continue any request handling if there's a filter configured and the value we've got is wrong.
The decision on this one is not easy and we had long discussion about it. As it is mainly a server configuration issue, putting too much code about it into already complex Request class does not seem right. Both sides have good arguments but we came to the conclusion that education in the guide + a behavior which is independent of Request class is good way to deal with this.
Thanks to all for providing your input on this!
Please at least consider setting Request::$hostInfo
to some safe value (empty string in worst case) if host is invalid. Keeping corrupted host in Request::$hostInfo
is just asking for trouble - it is easy to imagine situation when someone will use Request::$hostInfo
in denyCallback
and having relative URLs is still better than URLs with invalid host.
@rob006 if validation is enabled, there will be no chance to actually use hostInfo because request will be terminated with an error early.
@rob006 in denyCallback there is a warning in the docs to not use it.
@samdark You could write your own denyCallback
which use Request::$hostInfo
.
@cebe I don't think it is enough. Request::$hostInfo
is used implicit in many places, it is easy to use it without even know about that. For example, redirecting to correct domain is probably valid solution and some people will prefer this instead of showing ugly 404 error. But using Yii::$app->getResponse()->redirect(['/home'])
is insecure, since it will use corrupted host info to create URL for redirection, and this is not obvious.
In the other hand introducing property like HostControl::$defaultHostInfo
which will replace invalid host info, will simplify everything. After setting this property you could safely use redirection and even show regular error page.
You mean HostControl
should explicitly set Request::$hostInfo
to a value trusted by us before calling denyCallback? Sounds like a good thing to me.
I don't see why this is an issue.
hostInfo
.@samdark You can override default error handler by custom action, and then you can (accidentally) use
Request::$hostInfo
(which is super easy, since lots of code use UrlManager
which use Request::$hostInfo
). In fact even current implementation of error handling is not bulletproof - you can attach into Response::EVENT_BEFORE_SEND
event that use Request::$hostInfo
and then your app is still vulnerable to "Host Header Attack" even with HostControl
filter enabled.
Right. This case with error handler is indeed possible. @klimov-paul thoughts?
You can override default error handler by custom action, and then you can (accidentally) use
Request::$hostInfo (which is super easy, since lots of code use UrlManager which use Request::$hostInfo)
That is why HostControll::denyCallback()
uses own implementation for 404 page without using native error handler mechanism.
That is why HostControll::denyCallback() uses own implementation for 404 page without using native error handler mechanism.
It uses Response::send()
which call Response::EVENT_BEFORE_SEND
events which may use Request::$hostInfo
. HostControll::denyCallback()
does not prevent using corrupted Request::$hostInfo
.
And what is the use case for keeping invalid host in Request::$hostInfo
?
And what is the use case for keeping invalid host in Request::$hostInfo?
It's not the use case. We just assume it will never be used since app is terminated immediately.
@rob006 would the following patch match your proposal?
diff --git a/framework/filters/HostControl.php b/framework/filters/HostControl.php
index d89129d..ff73665 100644
--- a/framework/filters/HostControl.php
+++ b/framework/filters/HostControl.php
@@ -106,6 +106,9 @@ class HostControl extends ActionFilter
*/
public $denyCallback;
+ // could be null and exception forces to set it
+ public $safeHostInfo = 'example.com';
+
/**
* @inheritdoc
@@ -132,6 +135,9 @@ class HostControl extends ActionFilter
}
}
+ // set hostInfo in deny case
+ Yii::$app->request->hostInfo = $this->safeHostInfo;
+
if ($this->denyCallback !== null) {
call_user_func($this->denyCallback, $action);
} else {
@cebe More or less. I will open PR with my proposal.
@TerraSkye said:
no matter what point u look at it, its a server configuration fault, wich shouldnt be solved in YII,
as proposed above we can have a filter wich does an additional check,
Imo thats the best we can do, i mean there can be many more problems when the server isnt configured right.
@cebe said:
The decision on this one is not easy and we had long discussion about it. As it is mainly a server configuration issue, putting too much code about it into already complex Request class does not seem right. Both sides have good arguments but we came to the conclusion that education in the guide + a behavior which is independent of Request class is good way to deal with this.
Thanks to all for providing your input on this!
Please read carefully my comment above.
I don't think that folks developing Django and Symfony added it just because it's "nice feature to have". Turns out that server configuration is not enough.
I have one project written in Django. And in the log there are MANY entries like that:
[Django] ERROR (EXTERNAL IP): Invalid HTTP_HOST header: '***.appspot.com'.
You may need to add '***.appspot.com' to ALLOWED_HOSTS.
Sometimes server IP appears in such messages too.
I get many messages of this type daily.
So I still think it's better to add this to the core.
@arogachev it's already there.
Most helpful comment
$_SERVER['SERVER_NAME']
is somethign configured at server side. It can contain random string. As well as it can contain something like*.example.com
, which is invalid domain name either.Indeed in correctly configured web server it will contain the host name, but in correctly configured web server you will be unable to access application from invalid host.