Hardening de Nginx: La Guía para Amplificar tu Seguridad (con todo lo que puede salir mal si no lo haces) Cada línea de configuración por defecto de Nginx que ignoras es una puerta entreabierta. Esta guía muestra exactamente lo que cada una significa en la práctica — y cómo cerrarla, una por una.
Hardening de Nginx: La Guía para Amplificar tu Seguridad (con todo lo que puede salir mal si no lo haces) Cada línea de configuración por defecto de Nginx que ignoras es una puerta entreabierta. Esta guía muestra exactamente lo que cada una significa en la práctica — y cómo cerrarla, una por una. Introducción Nginx nació en 2004 con una propuesta diferente de Apache: ser ligero, rápido y manejar miles de conexiones simultáneas sin problemas. En 20 años se convirtió en el servidor web más usado del mundo entre los sitios del top 1 millón. Y, exactamente como Apache, su configuración predeterminada está diseñada para funcionar en cualquier lugar — no para ser segura en cualquier lugar . La buena noticia es que Nginx tiene una configuración más limpia y centralizada que Apache. La mala noticia es que justamente por eso, cuando algo está mal, está mal en todos los sitios a la vez. Esta guía sigue la misma lógica del post anterior sobre Apache: para cada elemento, explicamos qué hace la configuración predeterminada , qué puede hacer un atacante con eso (con escenarios reales), y cómo corregirlo con configuración lista para copiar. server tokens: Nginx también grita su versión Qué sucede por defecto Toda respuesta de Nginx incluye un header Server así: Y en páginas de error, aparece un pie de página igualmente revelador. Qué causa esto Un atacante escanea internet con Shodan, Censys o un script Filtra por "nginx/1.24.0" — encuentra todos los CVEs de esa versión Filtra exploits listos en Exploit-DB, Metasploit, GitHub Si tu versión tiene una vulnerabilidad no corregida, el ataque comienza en segundos Agravante específico de Nginx: mucha gente ejecuta versiones compiladas con módulos de terceros (Brotli, ModSecurity, RTMP) que quedan atrás en las actualizaciones. La corrección Para esconder completamente el header (no solo la versión), usa el módulo headers-more: fastcgi param SERVER SOFTWARE: la fuga vía PHP Qué sucede por defecto Cuando Nginx pasa solicitudes a PHP-FPM, envía automáticamente una variable SERVER SOFTWARE con la versión de Nginx. Combinado con expose php = On, filtra versión de ambos. Qué causa esto El mismo problema del item anterior, al doble. El atacante descubre versión de Nginx y de PHP con una única solicitud. La corrección En php.ini: En el bloque PHP de Nginx: La directiva fastcgi hide header impide que los headers provenientes del upstream se devuelvan al cliente. Úsala siempre. Métodos HTTP peligrosos Qué sucede por defecto Nginx acepta cualquier método HTTP que envíe el cliente y lo pasa a la aplicación backend. Qué causa esto API mal protegida que acepta DELETE /api/users/123 sin autenticación adecuada Aplicación Node/Python con ruta PUT abierta por error WebDAV mal configurado en otro componente Escáneres de cumplimiento marcando como vulnerabilidad La corrección Para APIs REST que necesitan PUT, DELETE, PATCH: Strict-Transport-Security (HSTS) Qué sucede por defecto Nginx no envía HSTS. Incluso en sitios HTTPS-only, el navegador hace la primera solicitud vía HTTP hasta recibir redirect. Qué causa esto SSL Stripping : un atacante en Wi-Fi público intercepta la primera solicitud HTTP, mantiene conexión HTTP con la víctima y HTTPS con el servidor real. La víctima nunca ve el candado, pero digita la contraseña de todas formas. Con HSTS, el navegador se niega a hablar HTTP con el dominio después de la primera visita. El ataque deja de funcionar. La corrección ADVERTENCIA CRÍTICA sobre always: sin este sufijo, el header solo se envía en respuestas exitosas y redirect, no en respuestas de error . Con always, se envía en todas. Usa siempre always en headers de seguridad en Nginx. Advertencia sobre HSTS en sí: una vez aplicado con max-age largo, el navegador bloquea el dominio en HTTPS. Si el certificado expira, los usuarios quedan sin acceso. Comienza con max-age=300 (5 minutos), valida todo, luego aumenta. X-Frame-Options: clickjacking Qué sucede por defecto Sin este header, cualquier sitio puede incrustar el tuyo dentro de un iframe. Qué causa esto Clickjacking : un atacante crea cualquier sitio (sorteo, juego) que carga tu panel admin dentro de un iframe invisible, con botones falsos superpuestos. La víctima — logueada en otra pestaña de tu sistema — hace clic en "ganar premio" y en realidad hace clic en "eliminar cuenta" en tu panel. La corrección X-Content-Type-Options: MIME sniffing Qué sucede por defecto Cuando recibe un archivo con Content-Type ambiguo, el navegador trata de adivinar el tipo real mirando el contenido (MIME sniffing). Qué causa esto Un atacante envía foto.png con contenido HTML/JavaScript dentro. Tú validas solo la extensión. Cuando otra víctima accede, el navegador mira el contenido, piensa "esto es HTML" y lo ejecuta. XSS almacenado sin ni siquiera necesitar burlar un filtro. La corrección Referrer-Policy Qué sucede por defecto Cuando el usuario hace clic en un enlace externo, el navegador envía al destino la URL completa de origen. Qué causa esto Supón URLs como: Cua…