yii2: host header attack problem
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.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 5
- Comments: 104 (104 by maintainers)
Commits related to this issue
- Added documentation about Host header attack Added info about Host header attack (#13050) to the guide and the Request class. When we introduce a filter or property to protect against this, these sec... — committed to yiisoft/yii2 by cebe 8 years ago
- Added documentation about Host header attack (#13073) * Added documentation about Host header attack Added info about Host header attack (#13050) to the guide and the Request class. When we intro... — committed to yiisoft/yii2 by cebe 8 years ago
- Added documentation about Host header attack (#13073) * Added documentation about Host header attack Added info about Host header attack (#13050) to the guide and the Request class. When we intro... — committed to SilverFire/yii2 by cebe 8 years ago
$_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.
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
trustedHostsproperty.@cebe More or less. I will open PR with my proposal.
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!
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.
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.
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 related section also can be useful - Host Header Validation.
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()andhome()useRequest::getHostInfo()UrlManagerandUrlRuleuseRequest::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.
That is why
HostControll::denyCallback()uses own implementation for 404 page without using native error handler mechanism.@samdark You could write your own
denyCallbackwhich useRequest::$hostInfo.@cebe I don’t think it is enough.
Request::$hostInfois 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 usingYii::$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::$defaultHostInfowhich will replace invalid host info, will simplify everything. After setting this property you could safely use redirection and even show regular error page.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 hostsconfigured 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.
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.How it will be different from current state?
At the present state following condition:
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.
Returning empty
host infowill 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.
I do not like such behavior. For me cases
host is invalidandthere is no host at allare different. I do not like to mix them up. For example: request, even with invalidHost 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.The problem is that
Request::getHostInfo()will return unsafe value. So I’m proposing to validate host info before it is returned byRequest::getHostInfo()(inbeforeRequest), you’re proposing doing this after this. So my proposal isthe earliest of the earliest as possible. 😃No?
Request::getHostInfo()will returnnullif host info is invalid. This should not brake anything.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.
Your implementation makes sense. I forgot about the behavior implications. Should’ve looked more carefully at the PR. 👍
See https://github.com/yiisoft/yii2/issues/13050#issuecomment-262253751 :
HostControlat #13063 allows specification of hots name as wildcard, e.g.*.example.com.@arogachev thanks for references. These are useful for docs.
PR with filter implementation: #13063