8000 Request should not trust any header names by default · Issue #20178 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Request should not trust any header names by default #20178

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

Closed
dzuelke opened this issue Oct 6, 2016 · 8 comments
Closed

Request should not trust any header names by default #20178

dzuelke opened this issue Oct 6, 2016 · 8 comments

Comments

@dzuelke
Copy link
Contributor
dzuelke commented Oct 6, 2016

(also see symfony/symfony-docs#7045)

http://symfony.com/doc/current/request/load_balancer_reverse_proxy.html and http://symfony.com/doc/current/components/http_foundation/trusting_proxies.html talk about trusting proxies, and http://symfony.com/doc/current/request/load_balancer_reverse_proxy.html#but-what-if-the-ip-of-my-reverse-proxy-changes-constantly in particular mentions AWS as an example.

AWS ELBs do not set a Forwarded header, making it necessary to follow the instructions at http://symfony.com/doc/current/request/load_balancer_reverse_proxy.html#my-reverse-proxy-sends-x-forwarded-for-but-does-not-filter-the-forwarded-header, but they also do not set an X-Forwarded-Host (only …-For, …-Port and …-Proto), which means, that for a very popular use case (running on AWS, or products that build on it, e.g. Heroku), applications would be vulnerable to spoofing of those headers.

My hunch is that a lot of developers don't realize that they need to explicitly distrust these headers, especially as the special case documentation and handling logic for Forwarded, unlike the other headers, has been introduced relatively recently.

I propose that out of the box, when a developer calls Request::setTrustedProxies(), no header names are trusted by default, and they must always be explicitly opted into using Request::setTrustedHeaderName(). That's only slightly more work, but means that the default is safe with an empty whitelist, and developers, having to investigate what headers really are being set in their environment, are much more likely to end up with valid settings that do not compromise application security.

/cc @fabpot, who asked me to open this issue (I may have time for a PR soon-ish)

@dzuelke
Copy link
Contributor Author
dzuelke commented Mar 30, 2017

@nicolas-grekas quick ping to see if this may be extra relevant/timely, as it's related to #21830

@nicolas-grekas
Copy link
Member
nicolas-grekas commented Mar 31, 2017

Nice, then we can close this one ! Here is why:
#21830 makes providing the trusted headers a requirement (a non enforced one for now to not break BC, but will be mandatory in 4.0).
So, setTrustedProxies takes the set of trusted headers as 2nd args.
Typically:
Request::setTrustedProxies(array(127.0.0.1), Request::HEADER_FORWARDED);
or
Request::setTrustedProxies(array(127.0.0.1), Request::HEADER_X_FORWARDED_ALL);

but really, this 2nd arg is a bitfield, so that in AWS ELBs, you just need to do eg:
Request::setTrustedProxies(array(127.0.0.1), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);

Done!
Would you mind doing the doc PR solving symfony/symfony-docs#7045?

@dzuelke
Copy link
Contributor Author
dzuelke commented Mar 31, 2017

Okay, but in 3.3, just Request::setTrustedProxies(array(127.0.0.1)) will continue to trust all the headers, correct?

It might be worth considering changing that default even in 3.3, to "immediate breakage", in the interest of security, as 99.975% of code out there does that call in app.php or similar, and would need touching only once during upgrading (which could be documented).

Or at least change it in 3.4, as that will be the LTS version, and I really really really really really think the defaults are harmful.

But I'll let you decide that :)

@fabpot
Copy link
Member
fabpot commented Apr 1, 2017

I agree with @dzuelke here that we should make the second new arg mandatory as of 3.3. But I would not make the default "optimized" for AWS, that's a doc issue instead IMHO.

@nicolas-grekas
Copy link
Member

Done in #22238
@dzuelke would you mind doing the doc PR?

@robfrawley
Copy link
Contributor

Very must support this "BC-break" in the immediately next minor version, as well.

@dzuelke
Copy link
Contributor Author
dzuelke commented Apr 3, 2017

Can do @nicolas-grekas, want to give me a deadline?

@nicolas-grekas
Copy link
Member

May 15th if possible, that should match the first betas of 3.3

fabpot added a commit that referenced this issue Apr 3, 2017
…) takes a new required $trustedHeaderSet argument (nicolas-grekas)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[BC BREAK][HttpFoundation] Request::setTrustedProxies() takes a new required $trustedHeaderSet argument

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | yes
| New feature?  | yes
| BC breaks?    | yes
| Deprecations? | yes
| Tests pass?   | yes
| Fixed tickets | #20178
| License       | MIT
| Doc PR        | -

As discussed in linked issue, and already deprecated by #21830

Commits
-------

72e2895 [BC BREAK][HttpFoundation] Request::setTrustedProxies() takes a new required $trustedHeaderSet argument
@fabpot fabpot closed this as completed Apr 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants
0