Problem/Motivation
DRUPAL-SA-CORE-2016-003 introduced a new url rewriting rule in which the HTTP_PROXY header is cleared in web.config:
<rule name="Erase HTTP_PROXY" patternSyntax="Wildcard">
<match url="*.*" />
<serverVariables>
<set name="HTTP_PROXY" value="" />
</serverVariables>
<action type="None" />
</rule>
In order to allow the urlrewrite module (for security reasons!) to add/alter/remove server variables users are required to add a new configuration setting (either through the UI or in applicationHosts.config):
https://technet.microsoft.com/es-es/library/ee619775(v=ws.10).aspx
By introducing that change, all IIS deployments have broken in a way that is difficult to diagnose and fix.
The error the user is presented with is this one:
HTTP Error 500.50 URL Rewrite Module Error - The server variable "HTTP_PROXY" is not allowed to be set. Add the server variable name to the allowed server variable list.
I'm not sure this qualifies as critical, but considering that IIS is considered as a supported web server, and that drupal ships with a web.config, breaking all IIS installs sounds to me as critical....
https://www.drupal.org/docs/7/system-requirements/web-server
The issue here is that the complimentary setting (allowed server variable) cannot be added in the web.config file, it needs to be setup at the applicationHosts.config level:
https://forums.iis.net/t/1187303.aspx
http://stackoverflow.com/questions/35634361/where-should-allowedservervariables-tag-live-in-azure-website-applicationhost
A possible solution is to evaluate properly if the newly included rule is really necessary and remove it if not.
Proposed resolution
- Do not enforce the Url Rewrite rule by default.
- Warn the user in the status page (REQUIREMENT_ERROR) when running on a PHP version affected by the issue and the mitigation IIS rewrite rule is not enabled.
With these changes:
- Users running on safe PHP environments/setups will notice nothing.
- Sites that were broken by DRUPAL-SA-CORE-2016-003 will instead keep running with a security warning/error in all admin pages.
- New installs will be blocked with an error until they properly setup their environment or update the PHP runtime.
Remaining tasks
RTBC
User interface changes
New warning in status/install when user is running a PHP version affected by Httpoxy and the web.config has not been properly set up.
API changes
None
Data model changes
None
Comment | File | Size | Author |
---|---|---|---|
#34 | iis-httpoxy-2783079-33.patch | 2.88 KB | david_garcia |
#32 | iis-httpoxy-2783079-32.patch | 2.88 KB | david_garcia |
#29 | iis-httpoxy-2783079-16.patch | 2.82 KB | david_garcia |
#26 | iis-httpoxy-2783079-26.patch | 3.93 KB | david_garcia |
#23 | iis-httpoxy-2783079-23.patch | 4 KB | david_garcia |
Comments
Comment #2
david_garcia CreditAttribution: david_garcia commentedComment #3
david_garcia CreditAttribution: david_garcia commentedComment #4
david_garcia CreditAttribution: david_garcia commentedComment #5
alexpottAll we did we implement Microsoft's advice see https://support.microsoft.com/en-us/kb/3179800 - if that advice doesn't work is that our fault?
Comment #6
david_garcia CreditAttribution: david_garcia commented@alexpott I am blaming no-one. I'm just saying this needs to be fixed or looked at. I'm looking into what the best solution is, will report when done.
Comment #7
david_garcia CreditAttribution: david_garcia commentedInvestigated this....
The microsoft article states that CGI applications are affected, not fastCGI. No one is using (or should even consider using) the old CGI for hosting applications on IIS.
But later on they say:
So I setup a sample script and did some tests, and can confirm that HTTP_PROXY is NEVER set by PHP itself in any way.
Running this script with and without sending a "Proxy" HTTP header will yield the same output:
To test this easily, use fiddler to modify the request headers on the fly.
My conclusion is that IIS+FastCGI is not affected by this issue, and that the URL Rewrite rule should be removed.
Comment #8
david_garcia CreditAttribution: david_garcia commentedTested this with different PHP versions.
PHP >= 7 is not affected by this issue.
PHP < 7 DOES EXHIBIT THE PROBLEM. The script in #7 does populate HTTP_PROXY server variable when used in PHP < 7.
Comment #9
david_garcia CreditAttribution: david_garcia commentedNot a definitive patch, but this is how I would deal with the issue:
This will not bother users with PHP >= 7 (where the issue does not exist) and will allow users with PHP < 7 to notice that they need to change some deployment setting instead of just breaking their sites.
Comment #12
alexpottThe PHP version thing is just probably reflecting which builds you tested with the latest PHP release... 5.6.23 and 5.5.37 both HTTP poxy fixes ... so does 7.0.8... but all the previous versions are vulnerable.
Comment #13
david_garcia CreditAttribution: david_garcia commentedTotallly right. Misssed out that they fixed this here:
https://bugs.php.net/bug.php?id=72573
Reading through the changelog it was fixed in 5.6.24, 5.5.38 and 7.0.9 releases.
Comment #14
alexpottWeird the latest releases aren't on https://secure.php.net/releases/ hence my error.
Comment #15
david_garcia CreditAttribution: david_garcia commentedUpdate patch to only show warning when the user is running any of the affected PHP versions.
Comment #16
david_garcia CreditAttribution: david_garcia commentedFixed how some of the warnings and comments are written.
Comment #17
alexpott@david_garcia I'm not sure this is critical tbh. If this breaks your webserver then you're probably not secure since I'd wager that many people using IIS are not on the latest PHP versions. In order to secure your webserver you have to configure your server correctly. IMO it would be critical if we continued to serve the site which with the current patch we'll continue to do. And if you think that the error given by IIS is not explicit enough that's a bug in IIS. To be honest the error looks pretty good.
Personally all I think we should do in this issue is an @todo to web.config and .htaccess to remove the http_poxy mitigations once the minimum version of Drupal is greater than 7.08. And perhaps we can add information about this to the security release notes.
Comment #18
david_garcia CreditAttribution: david_garcia commentedThat's wrong if you are running a safe PHP version.
What was implemented here is a partial (as it required additional manual setup otherwise it breaks your server) workaround for a bug in PHP, not in Drupal.
The fact that your server does not have the HTTP_PROXY as an allowed header does not mean that it is "incorrectly configured". Indeed, this was the first time ever I had heard about that IIS Rewrite feature.
It is explicit, the issue is that this setting is a "rare" and hidden feature that no one uses. And it's there for security.
What about promoting REQUIREMENT_WARNING to REQUIREMENT_ERROR? That would prevent clean installs without being secured, and will properly warn current installs.
The current patch has exponentially increased the barrier of entry for IIS deployments. You basically get a broken Drupal out of the box without a complex and additional manual setup (which by the way is not required at all if you run any of the latest PHP versions). And I can confirm this as I am behind the www.drupalonwindows.com website. I've been flooded with e-mails from people wondering what is going on with the out-of-the-box broken Drupal.
That's right, this is just a mitigation in the sense that as long as no code is relying on the HTTP_PROXY server variable (which has been already been fixed by Guzzle) there is no real exploitation case out there for Drupal 8 (if I'm right). I think it simply does not compensate the heavily increased barrier of entry for IIS users.
Comment #19
xjmThis is introduced in 8.1.x, so moving there.
Comment #20
Fabianx CreditAttribution: Fabianx as a volunteer and at Tag1 Consulting commentedWhat I never got about HTTPoxy was that they said, that unsetting via PHP is not enough to be secure.
If I see both the getenv() and the $_SERVER to bogus values - if its set at all, I can break an application that depends on the HTTP_PROXY environment var, but 99% of sites would not use that.
Also looking at the PHP code it is enough to unset it / set it to something else.
So a "fix" in PHP would break those installations using an obscure environment var (instead of proper config), but I know of no system that does.
So maybe in addition to the requirement warning, we could just unset the proxy header AND the getenv() on affected PHP versions. (and possibly allow an override for it via a hidden setting)
After all they could be using some obscure nginx config or something else or whatever ...
--
OT: The part "do not even bother to fix this in PHP - you can't."
was the most panic-y thing I disliked about the HTTPoxy thingy, because that creates unnecessary FUD.
Of course you can, you just break your application for the case where that env var is set, but using env vars for configuring a proxy is "meh" anyway ...
So put it in a variable, putenv() it and override $_SERVER and call it a day ...
--
TL;DR: Lets make Drupal secure out of the box for HTTPoxy (on unsupported configurations and IIS) by unsetting both things (getenv, $_SERVER) if using an affected PHP version; allow to override it (for the 0.00001% edge case) and warn about it in requirements, so that broken sites know where to look.
If I had to guess exactly 0% Drupal 8 sites use the environment variable to configure a proxy for the application.
Comment #21
david_garcia CreditAttribution: david_garcia commentedThis will only happen for users on IIS that are running an affected PHP version and the have not enabled the IIS rewrite rule in web.config
Behaviour for non IIS users remains intact with this patch.
Comment #22
alexpott@Fabianx see https://gist.github.com/alexpott/c3903713ac888b069b915975162dc718 - it gets quite complex to work this out - apache_setenv()... I wonder what the equivalent would be for IIS? nginx, etc...
This doesn't make sense to do in hook_install and also probably does not work.
Comment #23
david_garcia CreditAttribution: david_garcia commentedTotally right... sometimes rushing produces awful results.
Agreed. Unsetting the HTTP_PROXY environment variables will brake the same thing as the original DRUPAL-SA-CORE-2016-003 (anything depending on HTTP_PROXY would break), so we can harden this on the PHP side itself.
Yet, I am not sure how early in the request pipeline this should be placed. I've made an attempt, but not sure if this is the right place.
Comment #24
david_garcia CreditAttribution: david_garcia commentedComment #26
david_garcia CreditAttribution: david_garcia commentedRushing too much lately...
Comment #27
david_garcia CreditAttribution: david_garcia commentedComment #28
alexpottAs detailed several times this is not enough. I think the patch is fine without the mitigation since setting up Guzzle to not use environment variables is already done by core and this is the only likely vulnerability. If contrib or custom set up Guzzle and do not use the D8 provided service then they are on their own. We could say this in the SA to cover our backs.
Comment #29
david_garcia CreditAttribution: david_garcia commentedBack to the patch in #16. I don't think there is really anything from the PHP side that will have a real impact on the issue.
Comment #31
xjmProbably should also discuss how we mitigate (or don't) for IIS and older PHP versions with the sec team.
At a minimum, I think we need to update the SA with complete instructions for IIS (as well as maybe a pull request to httpoxy.org) and add this as a known issue in our release notes.
Isn't there a third option, something they can set in the IIS config?
Also, we should not link issues in UI text. Instead, we should update the official SA and link that, or possibly https://support.microsoft.com/en-us/kb/3179800, with an accessible link text.
Finally, I think the canonical form of the vulnerability name is all lowercase.
Should it be an error instead of a warning?
New sites will not be able to install until they fix it if we make it an error. Sites that are already installed are currently in a situation where they are broken, but protected. If we were to release this fix, they would start working again, but be vulnerable until they took additional mitigations. With it as an error, a message will be displayed on their admin pages, so they only know to mitigate it if they check the status report. Is that sufficient to mitigate the vulnerability when they update? Would it require a PSA?
Comment #32
david_garcia CreditAttribution: david_garcia commentedNot that I know about.
Patch now links to the SA (with an accessible link text).
To my understanding Httpoxyy is a proper noun, and thus must be capitalized.
Latest patch boosts this to REQUIREMENT_ERROR.
Comment #33
alexpottFor better or worse we should copy https://httpoxy.org/ and go lower case.
I like the solution of ensuring new installs have to address the issue before installing and existing sites still work but have a big warning.
Comment #34
david_garcia CreditAttribution: david_garcia commentedRemoved capitalization on usages of Httpoxy, really don't care about this picky detail but doing this because "that's what they do in other places" does not mean it is correct.
Comment #35
alexpottThe patch looks good - @david_garcia, I agree with you "that's what they do in other places" is often a bad thing but in this case we are talking about a name. If I insisted that my name is "alex" and that I always wanted it to be lowercase - that would be okay - because it is my name and therefore my right to call myself what I like and insist of capitalisation I prefer. The namers of httpoxy have made a choice - whether we like their choice or disagree is immaterial.
From a security perspective making the web.config change optional but with an error on the status report if not implemented is better than the current situation where if the rule breaks your site you'd be tempted to remove the rule and not upgrade PHP. Also in core and anything that uses the http_client service is not vulnerable because of other, earlier, mitigations.
Comment #36
catchI'd be happier if this sent an e-mail (for example if update status is configured to send security e-mail notifications). We can't always guarantee that people see hook_requirements() messages so theoretically we're making a site less secure (if they updated core, fixed their IIS config to allow the header or already had it set, then updated again to this version).
However since core itself isn't vulnerable, it might be OK to leave it like this.
Comment #37
alexpottTo clarify why core in it's default configuration is not vulnerable. As part of the httpoxy mitigations added to core we initialize the http_client service using the values in \Drupal\Core\Http\ClientFactory::fromOptions():
The only way of telling Drupal to use an outbound proxy is to follow the example settings in default.settings.php:
We used to say in default.settings.php that:
This is no longer true.
Maybe we should add some of this information to https://www.drupal.org/SA-CORE-2016-003?
Comment #38
catchOK I don't love this, but given the original patch was hardening rather than closing an actual security issue, it seems like the least worst option.
Committed/pushed to 8.3.x, thanks!
Leaving at 'to be ported' for 8.2.x, and agreed it would be good to add more information to the SA. @david_garcia would you be up for drafting something (if you post it here, one of us could edit it in easily from that).
It would be good to get that up before cherry-picking to 8.2.x, but it'd also be good to get this patch into 8.2.0, so see how it goes.
Comment #41
catchThat's been quiet, so cherry-picked to 8.2.x, thanks!