14 noviembre 2011

Fortificación de nginx

nginx es un popular servidor web y proxy inverso libre y gratuito que ya aloja más de 43 millones de dominios, entre los que se encuentra Wordpress, Dropbox, Facebook o TechCrunch.

En esta entrada vamos a ver algunos aspectos a configurar para que su instalación sea más segura.

Lo primero es eliminar información que identifique la versión de nginx todo lo que se pueda. Esto no hace el servicio más seguro, pero pone trabas a la hora de intentar buscarle fallos.

Para eliminar la cadena "nginx" de la cabecera Server, es necesario modificar el código fuente, en concreto del fichero  src/http/ngx_http_header_filter_module.c  siguientes líneas:

static char ngx_http_server_string[] = "Server: nginx" CRLF;
static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;

Por
static char ngx_http_server_string[] = "Server: httpd" CRLF;
static char ngx_http_server_full_string[] = "Server: httpd" CRLF;

Si únicamente se desea eliminar el número de versión, dejando  tan solo "nginx", o no se puede recompilar, en la configuración se puede especificar con la directiva:

server_tokens off;

Una vez instalado, hay que asegurarse de que no se ejecuta con un usuario con privilegios de administración. En su configuración ha de figurar el usuario y grupo son distintos de root.

user              nginx nginx;

La identificación de la versión también es posible si se observan los mensajes de error del servicio. Para asegurar que no se reporta en ningún momento lo mejor es modificar las siguientes líneas del fichero src/http/ngx_http_special_response.c:

static u_char ngx_http_error_full_tail[] =
"<hr><center>" NGINX_VER "</center>" CRLF
"</body>" CRLF
"</html>" CRLF
;


static u_char ngx_http_error_tail[] =
"<hr><center>nginx</center>" CRLF
"</body>" CRLF
"</html>" CRLF
;

Por otras que no incluyan la variable NGINX_VER:

static u_char ngx_http_error_full_tail[] = CRLF;
static u_char ngx_http_error_tail[] = CRLF;

También se puede especificar en el fichero de configuración, dentro de server {}, cuáles serán las páginas de error personalizadas para cada una de los errores. En este ejemplo se redirige a error.html:

error_page 400 401 402 403 404 405 406 407 408 
409 410 411 412 413 414 415 416 417 495 496 497 500 501 502 503 504 
505 506 507 /error.html;
location /error.html {
    internal;
}

Una vez modificado el código fuente, se compila deshabilitando todos los módulos que no se usen. La web de nginx facilita una lista completa con su descripción. Especialmente interesante de eliminar es el autoindex. Para deshabilitar se utiliza una línea como la siguiente:

./configure --with-http_ssl_module --without-http_autoindex_module
--without-http_browser_module --without-http_fastcgi_module
--without-http_geo_module --without-http_empty_gif_module 
--without-http_map_module  --without-http_proxy_module
--without-http_memcached_module --without-http_ssi_module
--without-http_userid_module  --with-http_ssl_module 

Como se gestionan los recursos dependerá más de las necesidades de rendimiento que de la propia seguridad, salvo se detecte y conozca algún fallo concreto. Si es posible y no impacta a este factor, se especifican tamaños de buffer pequeños donde sea más difícil explotar una vulnerabilidad.

client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;
client_body_timeout 10;
client_header_timeout 10;
send_timeout 10;
keepalive_timeout 60 60
send_timeout 60

Otra directiva interesante es activar la opción para ignorar todas las cabeceras invalidas:

ignore_invalid_headers   on;
Para deshabilitar métodos HTTP, la mejor opción es usar listas blancas, marcando únicamente aquellos que se vayan a utilizar. Esta configuración también afecta al rendimiento, ya que procesar la expresión regular es costoso. También es importante destacar que nginx no soporta el método TRACE, ni PUT/DELETE/MKCOL/COPY/MOVE siempre y cuando no se compile con soporte Webdav

if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 500;
}

Otras características interesantes son la posibilidad de devolver un código de error en base al user-agent o al referer con una expresión regular, tal y como se muestra en el siguiente ejemplo, que además no hace distinción entre mayúsculas y minúsculas al haber especificado: ~*

if ($http_user_agent ~* (acunetix|nikto) ) {
  return 500;
}
if ($http_referer ~* (porn|webcam|bing) ) {
return 500;
}

También es posible evitar que enlacen directamente a las imágenes (hotlinking)  desde la configuración de nginx:

location ~* (\.jpg|\.png|\.css)$ {
 if ($http_referer !~ ^(hxxp://www.sbd.com) ) {
  return 500;
 }
}
Por último, si el servicio necesita servir páginas mediante HTTPS, una configuración válida y robusta que evita el ataque BEAST es la siguiente:

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=2592000; includeSubdomains";

Aunque es aconsejable saber los requerimientos de navegación y comprobar los resultados en el servicio de análisis de SSL de Qualys.

5 comments :

jordiv dijo...

 Genial articulo, yo tengo esta referencia que siempre me ayuda :) https://calomel.org/nginx.html

Mal dijo...

Muy buenas recomendaciones, como siempre :)

David Gómez dijo...

Excelente artículo, nunca había encontrado información tan útil acerca de NGINX en ninguna parte, teniendo en cuenta de lo limitada que es la info acerca de este servidor web.

Pi dijo...

Y si ponemos algún día las fuentes haremos una fiesta...

Alejandro Ramos dijo...

www.nginx.com
donde dices que vas a dar la fiesta?
Gracias por tu comentario!

El 20/11/2011, a las 18:19, "Disqus" <>
escribió:

[image: DISQUS]