[security advisory] $http_host vs $host

B.R. reallfqq-nginx at yahoo.fr
Tue Mar 10 10:01:48 UTC 2015


You specifically configured nginx to pass the Host header ($http_host) to
the backend, thus the backend has only this piece of information
available...
If you specified $host to be passed over, you would not have this flaw in
your configuration.
nginx does exactly what you configured. By default there is no such header
set for the backend.

Moreover using a Host header as a 'security feature' is... strange at the
very least.

The difference between the host (machine) and the Host header is common,
and should not be relied on for security. Have you ever played with curl?
If you use auth_basic for security, you should follow the same process when
dealing with the backend. The $remote_user variable allows you to check
which user has been authenticated. I would pass that to the backend. No
user = no authentication.

The only 'security advisory' I see here is to teach some basic course about
security to your sysadmin.
---
*B. R.*

On Mon, Mar 9, 2015 at 7:56 PM, Gena Makhomed <gmm at csdoc.com> wrote:

> On 09.03.2015 19:25, Francis Daly wrote:
>
>  Unsafe variable $http_host was used instead of safe one $host
>>>>>
>>>>
>>>> I'm not sure how $http_host is less safe than $host. It is proxy_pass'ed
>>>> to the "real" redmine server as the Host header. That server must be
>>>> able to handle it safely anyway, no?
>>>>
>>>
>>> Such configuration allow to spoof nginx built-in server selection rules.
>>> because nginx will use server name from request line, but will provide
>>> to upstream completely different server name, from Host request header.
>>>
>>
>> It is true that $http_host is completely controlled by the client, and
>> $host is mostly controlled by the client. It is true that they can have
>> different values. I do not see that the difference is a security issue
>> in this case.
>>
>>
> 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;
>    }
> }
>
> in such configuration anybody can bypass nginx auth_basic restriction
> and access content from private.example.com without any login/password:
>
> GET https://public.example.com/top-secret.pdf HTTP/1.1
> Host: private.example.com
>
> nginx will use host name public.example.com for server selection,
> and process request in second server, but send to backend
> "Host: private.example.com" and relative URI in request line.
>
> and backend will process such request as request to private.example.com
>
> because backend server see only relative uri in request line,
> and will use host name from Host: request header in this case.
>
> =======================================================================
>
> for proxy_pass such bug can be fixed just by using always
> $host instead of $http_host in proxy_set_header Host directive.
>
> for fastcgi_pass such bug can be fixed only by using two nginx
> servers - first for frontend, and second for backend,
> because nginx send to fastcgi value of $http_host
>
> bug cause:
>
> fastcgi spec was created when only HTTP/1.0 exists
> and don't know about absoluteURI in request line -
> such feature was added in HTTP/1.1, after FastCGI spec.
>
>  So, $host must be used always with proxy_pass instead of $http_host.
>>>
>>
>> If the upstream server would do anything security-relevant with the Host:
>> header that it gets from nginx, it would do exactly the same with the
>> Host: header that it would get from the client directly, no?
>>
>
> No.
>
> 1) http://tools.ietf.org/html/rfc7230#section-5.5
>
> 2) http://nginx.org/en/docs/http/ngx_http_core_module.html
>
> $host
>     in this order of precedence: host name from the request line, or host
> name from the “Host” request header field, or the server name matching a
> request
>
> --
> Best regards,
>  Gena
>
> _______________________________________________
> nginx mailing list
> nginx at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx/attachments/20150310/3b53b942/attachment-0001.html>


More information about the nginx mailing list