Skip to content
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

Reasons to use '$http_host' instead of '$host' with 'proxy_set_header Host' in template ? #763

Open
slamont opened this issue Mar 13, 2017 · 1 comment

Comments

@slamont
Copy link

slamont commented Mar 13, 2017

Hi,
we had a situation where an app using VAADIN would output a broken pipe error after some timeout that we confirmed would happen only when 'proxy_set_header Host $http_host' is used.
Simply overriding 'proxy_set_header Host' to using '$host' instead of '$http_host' fixed it for us.

I'm trying to understand why it is set to '$http_host' in the template as my understanding is this is security flaw as it could be spoofed?
This is where this information come from : https://forum.nginx.org/read.php?2,257134,257189

Would it be acceptable to change the value of 'proxy_set_header Host $http_host' in the template to 'proxy_set_header Host $host' ?

If you want I can create the PR

@G-E-N-E
Copy link

G-E-N-E commented Mar 14, 2017

Spoofing is done via something like
curl -H "Host: notyourdomain.com" http://yoursite.com/

My understanding is that NGINX matched the server block not on http://yoursite.com/ but on notyourdomain.com

Configuration from the linked information

server {
    listen 443 ssl;
    server_name private.example.com;
    location / {
        auth_basic "closed site";
        auth_basic_user_file conf/htpasswd;
        proxy_set_header Host $http_host;
        proxy_pass http://backend;
    }
}

server {
    listen 443 ssl;
    server_name public.example.com;
    location / {
        proxy_set_header Host $http_host;
        proxy_pass http://backend;
    }
}

If you did
curl -H "Host: private.example.com" http://public.example.com

you'd match the server_name private.example.com and be asked for a password.
private.example.com:443 would be passed to the backend. (good)

if you did
curl -H "Host: public.example.com" http://private.example.com

you'd match the server_name public.example.com and not be asked for a password.
public.example.com:443 would be passed to the backend. (good)

The key point though is that changing the proxy_set_header Host to $host would not change this
behavior at all because the $host value would be equal to the $http_host value when the Host Request field is present.


Using $host has it's own vulnerability; you must handle the situation when the Host field is absent properly by defining default server blocks to catch those requests.

I think this is a more common mistake made in configuration that could be exploited.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants