Hardening — Asegurando NGINX

Josmell Chavarri
Feb 18, 2018 · 7 min read
  • Mínimo Privilegio Posible (MPP): Todo componente dentro de un sistema debe ejecutarse con los privilegios necesarios para cumplir con su rol y nada más. Un sitio web nunca debe correr como root porque no es necesario para dar servicio y lo único que puede suceder es que un atacante que consiga vulnerar el sitio obtenga esos privilegios de root en el sistema.
  • Defensa en Profundidad (DP): Se deben implementar todas las medidas de seguridad que sean posibles, teniendo en cuenta dos factores:
server_tokens off;
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;
static u_char ngx_http_error_full_tail[ ] = CRLF;static u_char ngx_http_error_tail[ ] = CRLF;
static char ngx_http_server_string[ ] = “Server: nginx” CRLF;static char ngx_http_server_full_string[ ] = “Server: “ NGINX_VER CRLF;
static char ngx_http_server_string[ ] = “Server: httpd” CRLF;static char ngx_http_server_full_string[ ] = “Server: httpd” CRLF;
./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
user              nginx nginx;
error_page 400 401 402 403 404 405 406 407 408409 410 411 412 413 414 415 416 417 495 496 497 500 501 502 503 504505 506 507 /error.html;location /error.html {internal;}
## Size Limits & Buffer Overflows## the size may be configured based on the needs.client_body_buffer_size  100K;client_header_buffer_size 1k;client_max_body_size 100k;large_client_header_buffers 2 1k;
## Timeouts definition ##client_body_timeout 10;client_header_timeout 10;keepalive_timeout 5 5;send_timeout 10;## End ##
# find /nginx -name '.?*' -not -name .ht* -or -name '*~' -or -name '*.bak*' -or -name '*.old*'# find /usr/local/nginx/html/ -name '.?*' -not -name .ht* -or -name '*~' -or -name '*.bak*' -or -name '*.old*'
ignore_invalid_headers on;
if ($request_method !~ ^(GET|HEAD|POST)$ ) {return 500;}
# deny scripts inside writable directorieslocation ~* /(directorio| directorio | directorio | directorio | tmp)/.*.(php|pl|py|jsp|asp|sh|cgi)$ {return 403;error_page 403 /error_page.html;}
#bloquear sparmmersif ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) ){return 403;}
#Bloquear Agentes y robotsif ($http_user_agent ~* (acunetix|sqlmap|nikto|metasploit|hping3|maltego|nessus|webscarab|sqlsus|sqlninja|aranchni|netsparker|nmap|dirbuster|zenmap|hydra|owasp-zap|w3af|vega|burpsuite|aircrack-ng|whatweb|medusa) ) {return 403;}
## Block some nasty robotsif ($http_user_agent ~ (msnbot|Purebot|Baiduspider|Lipperhey|Mail.Ru|scrapbot) ) {return 403;}
## Block download agentif ($http_user_agent ~* LWP::Simple|wget|libwww-perl) {return 403;}
proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

#Para compatibilidad con IE6 y WINXP los siguientes
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";

#Usar una clave Diffie-Hellman > 2048, se puede generar con el comando
# cd /etc/ssl/certs; openssl dhparam -out dhparams.pem 4096
ssl_dhparam /etc/ssl/certs/dhparam.pem;

#No usar SSLv2 / SSLv3 / TLSv1
ssl_protocols TLSv1.1 TLSv1.2;

#Usar la preferencia del servidor y no la del cliente.
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;

#Otras recomendaciones cabeceras HTTP
ssl_session_timeout 10m;
# X-Frame-Options is to prevent from clickJacking attack
add_header X-Frame-Options SAMEORIGIN;
# disable content-type sniffing on some browsers.
add_header X-Content-Type-Options nosniff;
# This header enables the Cross-site scripting (XSS) filter
add_header X-XSS-Protection "1; mode=block";
# This will enforce HTTP browsing into HTTPS and avoid ssl stripping attack
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

ssl_session_tickets off;
ssl_stapling on; # Requires nginx >= 1.3.7
ssl_stapling_verify on;
keepalive_timeout 60;
# X-Frame-Options is to prevent from clickJacking attackadd_header X-Frame-Options SAMEORIGIN;# disable content-type sniffing on some browsers.add_header X-Content-Type-Options nosniff;# This header enables the Cross-site scripting (XSS) filteradd_header X-XSS-Protection “1; mode=block”;# This will enforce HTTP browsing into HTTPS and avoid ssl stripping attackadd_header Strict-Transport-Security “max-age=31536000; includeSubdomains;”;

Guayoyo

Blog oficial de Guayoyo — Anuncios, actualizaciones, noticias e información de interés

Josmell Chavarri

Written by

Especialista en Seguridad de la Información. Co-Fundador de @GuayoyoLabs #Venezolano “Lee y conducirás, no leas y serás conducido”.

Guayoyo

Guayoyo

Blog oficial de Guayoyo — Anuncios, actualizaciones, noticias e información de interés