HSTS: Protege tu web contra ataques Man in the Middle
HTTPS ofrece una capa de seguridad bastante buena (sobre todo si lo comparamos con el protocolo HTTP). Sin embargo, aún hay mejoras que debemos realizar para una mayor protección.
Para empezar, deberíamos utilizar OCSP Stapling, una técnica para validar los certificados SSL en el lado del servidor, mejorando así tanto velocidad como seguridad.
Otro problema conocido de HTTPS es que ¡puede ser vulnerable a ataques Man In The Middle (MITM)!
¿Qué es un ataque Man In The Middle?
Imaginemos que Juan está hablando con Sandra. Para comunicarse, aunque no se hayan dado cuenta, están confiando en una tercera persona (en este caso, un servidor web) para enviar correctamente los mensajes entre ellos.
Ahora biem, si esta conversación no se produjera a través de un canal seguro, alguien (Man In The Middle) puede interceptar los mensajes y cambiarlos sin que nadie se de cuenta. Problemón, ¿no?
Proteger tu web de ataques Man In The Middle utilizando HSTS
Cuando escribes en tu navegador, por ejemplo, "raullg.com", tu navegador intentará cargar la versión HTTP (insegura) por defecto. Esto ocurre porque el navegador no puede presuponer que tu página tiene un certificado SSL válido. Por ello, cargará primero la versión HTTPS y, si está bien configurada, le redirigirá a la versión segura HTTPS.
Esta primera conexión es insegura y, por tanto, susceptible de ataques MITM.
Afortunadamente, es un problema relativamente fácil de solucionar gracias a HTTP Strict Transport Security (HSTS). HSTS es una cabecera que indica al navegador web que únicamente puede aceptar conexiones seguras. Esto se hace utilizando la cabecera de Strict-Transport-Security
, especificando el período de tiempo en segundos en el que los navegadores solo deben aceptar conexiones a través de HTTPS.
Este es un ejemplo de una configuración HSTS de un año:
Strict-Transport-Security: max-age=31536000
Para entornos de desarrollo y staging, se recomienda utilizar 6 meses como max-age
. Para entornos de producción, la configuración más común son 2 años.
Maximizando la seguridad de HSTS
Además, HSTS se puede configurar para ser aplicado en todos los subdominios
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Al incluir preload
, el navegador utilizará HSTS para todas las conexiones incluida la primera.
Incluyendo nuestra web en la lista de HSTS
Para hacer todo el proceso más rápido y seguro, los navegadores descargan periódicamente un listado de todos los dominios y subdominios que tienen HSTS configurado. Sin embargo, esta lista no es automática y tenemos que cumplir unos requisitos para ser incluidos en ella:
- Nuestra web debe utilizar un certificado SSL válido
- Debemos redirigir todo el tráfico de HTTP a HTTPS
- Todos los subdominios deben funcionar a través de HTTPS
- La configuración HSTS debe tener un
max-age
de, al menos, 1 año (aunque se recomiendan 2). Además, debe utilizar las directivas deincludeSubdomains
ypreload
. - La redirección de HTTP a HTTPS también debe contener la cabecera de HSTS
Una vez estemos seguros de cumplir los requisitos, podremos enviar nuestra web a HSTS Preload. Para hacerlo, simplemente tendremos que introducir nuestro dominio en el campo de texto y aceptar las condiciones.
Atención: Consideraciones especiales
Activar HSTS en un dominio mal configurado puede traer bastantes problemas, ya que los navegadores bloquearán el acceso a los subdominios que no estén bien configurados.
Configurar HSTS utilizando .htaccess
Para configurarlo, solamente tenemos que incluir la siguiente cabecera en nuestro .htaccess
:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Configurar HSTS utilizando NGINX
NGINX también nos lo pone fácil para configurar HSTS:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
Configurar HSTS utilizando PHP
Aunque recomiendo encarecidamente configurar HSTS a nivel de servidor, a veces no tenemos acceso o permisos para hacerlo y tenemos que configurarlo a través de código. Para hacerlo en PHP, simplemente hay que llamar a la función header
con el valor correspondiente:
header("Strict-Transport-Security: max-age=31536000; includeSubDomains; preload");
Configurar HSTS en Laravel
En Laravel podemos utilizar un Middleware global para configurar HSTS:
namespace App\Http\Middleware;
use Closure;
class EnsureHSTS
{
public function handle($request, Closure $next)
{
return $next($request)
->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
}
}
Configurar HSTS utilizando ExpressJS en NodeJS
En su documentación, ExpressJS nos recomienta utilizar Helmet para securizar nuestra página web. Para ello, primero debemos instalar Helmet:
$ npm install helmet
A continuación, añadimos Helmet a nuestra aplicación de ExpressJS:
const express = require("express")
const helmet = require("helmet")
const app = express()
app.use(helmet())
Configurar HSTS en Django
Como siempre, Python nos da una de las soluciones más sencillas :-) Para activarlo, simplemente tenemos que añadir la siguiente configuracion en nuestro settings.py
:
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
Resumen
HSTS es esencial para evitar ataques MITM. Por tanto, debemos configurarlo correctamente y, si es posible, enviar nuestra web a la lista de HSTS Preload.