Opened 11 years ago

Last modified 11 years ago

#523 new enhancement

Information leak with automatic trailing slash redirect

Reported by: Vincent Boisard Owned by:
Priority: minor Milestone:
Component: nginx-core Version: 1.4.x
Keywords: Cc:
uname -a: Linux redacted.host 2.6.32-50-server #112-Ubuntu SMP Tue Jul 9 20:45:08 UTC 2013 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.4.4
built by gcc 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1)
TLS SNI support enabled
configure arguments: --prefix=/opt/nginx-1.4.4-2.1.1 --with-http_ssl_module --with-http_gzip_static_module --with-http_stub_status_module --with-cc-opt=-Wno-error --add-module=/opt/ruby-2.1.1/lib/ruby/gems/2.1.0/gems/passenger-enterprise-server-4.0.25/ext/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi_temp --http-scgi-temp-path=/var/lib/nginx/scgi_temp --with-debug --with-http_stub_status_module --with-http_flv_module --with-http_dav_module --with-http_realip_module --with-mail --with-mail_ssl_module --with-ipv6 --add-module=headers-more-nginx-module

Description

Hi,

Under specific circumstances, Nginx leaks information regarding the topology of the underlying infrastructure.

If no server name is specified (server_name _;, not uncommon for multi-tenant webapps) and no Host header is passed in a HTTP/1.0 request on a resource that is a directory, then the redirect uses the IP address of the server as the host part of the Location header in the response.

This assumes a location block like this one:

location ~* ^/(favicon.ico$|javascripts|assets|images|stylesheets) {
    # Do things
    break;
}

This might not be a big issue for a server that is directly accessible from the Internet, but in a configuration where the servers are in a VLAN behind a Load-Balancer, the IP leaked is the private network IP, which should never be made public.

I believe that if Nginx isn't able to construct a response without using private information such as port or IP address, then it should refrain from responding and terminate the request. At the least, an option to disable this behaviour would be nice.

Here is a more graphic representation of the problem (this assume a server with private IP 192.168.1.15 behind a LB):

$> nc -nv 1.2.3.4 80
found 0 associations
found 1 connections:
     1:	flags=82<CONNECTED,PREFERRED>
	outif en1
	src 192.168.10.15 port 57239
	dst 1.2.3.4 port 80
	rank info not available
	TCP aux info available
Connection to 1.2.3.4 port 80 [tcp/*] succeeded!

HEAD /images HTTP/1.0

HTTP/1.1 301 Moved Permanently
Date: Tue, 18 Mar 2014 10:49:07 GMT
Content-Type: text/html
Content-Length: 178
Location: http://192.168.1.15/images/ <= private IP leaked
Connection: close
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: public, max-age=315360000

Change History (4)

comment:1 by Valentin V. Bartenev, 11 years ago

Do you have server_name_in_redirect on in your configuration?

comment:2 by Vincent Boisard, 11 years ago

Thanks for answering so fast!
No, I do not have server_name_in_redirect on in my configuration.

comment:3 by Valentin V. Bartenev, 11 years ago

Type: defectenhancement

Then you should enable server_name_in_redirect and set appropriate server_name. It's definitely not a defect, since it works as expected.

Last edited 11 years ago by Valentin V. Bartenev (previous) (diff)

comment:4 by Vincent Boisard, 11 years ago

Thank you for your feedback.
According to the documentation, if the server_name_in_redirect option is set to on, then the server_name will always be used, even if the Host header is set.

While this would solve the leak problem, it would return a meaningless URL in the Location header of the redirect in a multi-tenant setting, where each client has its own Host.

Just to be sure : There is no way to make it so the host part in the redirect is the requested Host, with a fallback to the server_name in case it's not set ?

Note: See TracTickets for help on using tickets.