Saltar al contenido

Cookies y seguridad HTTP

Cómo se le devuelve la memoria a un protocolo que no la tiene, qué atributos protegen una cookie, y las cuatro piezas de seguridad que viven en las cabeceras: BASIC, CORS, HSTS y CSP.

Por qué hacen falta las cookies

Si el servidor no recuerda nada entre una petición y la siguiente, no puede existir el concepto de «usuario que ha iniciado sesión»: cada clic sería un desconocido llamando a la puerta. La cookie resuelve exactamente eso, y lo hace sin tocar el protocolo, aprovechando que las cabeceras son extensibles.

El mecanismo es que el estado lo guarda el cliente y lo reenvía él mismo en cada petición. El servidor sigue sin recordar nada; lo que hace es reconocer lo que le llega. Un detalle que se pregunta: el navegador manda todas las cookies válidas para ese dominio en cada petición, aunque el servidor no las necesite, lo que penaliza el tamaño de las peticiones si se abusa de ellas.

HTTP sigue sin estado. Lo que hay es un estado que viaja de ida y vuelta en cada petición, y por eso protegerlo es tan importante.

Para el examen

  • Qué resuelve la cookie: dar memoria a un protocolo sin estado

  • Cómo llega: el servidor la manda con Set-Cookie

  • Cómo vuelve: el navegador la devuelve en cada petición

HttpOnly, Secure y SameSite

Tres atributos más no controlan el alcance sino la seguridad, y son los que caen en el examen. Cada uno tapa un agujero distinto.

AtributoQué impideContra qué ataque
HttpOnlyQue el código JavaScript de la página pueda leer la cookieRobo de sesión mediante scripts inyectados (XSS)
SecureQue la cookie viaje por una conexión sin cifrarInterceptación del identificador de sesión en la red
SameSiteQue la cookie se envíe en peticiones originadas por otro sitioPeticiones falsificadas desde otro dominio (CSRF)

SameSite admite tres valores: Strict no la envía nunca desde otro sitio, ni siquiera al llegar por un enlace; Lax, que es el comportamiento por defecto de los navegadores actuales, la envía solo en navegaciones de primer nivel; y None la envía siempre, pero entonces es obligatorio marcar también Secure.

La sesión propiamente dicha suele ser un identificador aleatorio dentro de la cookie, mientras que los datos del usuario se guardan en el servidor. La alternativa sin sesión, en la que el propio testigo lleva dentro la información firmada, es JWT, y se estudia en el tema de servicios web del bloque de Desarrollo.

Para el examen

  • HttpOnly: impide leerla desde JavaScript; protege del XSS

  • Secure: la limita a HTTPS

  • SameSite: la defensa contra el CSRF

Autenticación BASIC

Es el esquema de autenticación más antiguo del protocolo y sigue cayendo porque su funcionamiento es muy preguntable. El servidor responde 401 con la cabecera WWW-Authenticate indicando el esquema Basic, el navegador muestra su propia ventana de usuario y contraseña, y repite la petición añadiendo la cabecera Authorization.

http
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Zona de administración"


GET /admin HTTP/1.1
Host: www.llegandoalcorte.com
Authorization: Basic ZGllZ286c3UtY29udHJhc2XDsWE=

Lo que viaja detrás de la palabra Basic es el usuario y la contraseña unidos por dos puntos y codificados en Base64. Base64 no es cifrado: es una representación reversible que cualquiera puede deshacer al instante. Por eso BASIC solo es admisible sobre HTTPS, donde lo que protege el secreto es TLS y no el esquema.

El reto de BASIC es siempre un 401 con WWW-Authenticate. El 403 no forma parte de este intercambio: es la respuesta a alguien ya identificado que no tiene permiso.

Para el examen

  • Cómo manda las credenciales: en Base64

  • Qué NO es Base64: cifrado

  • Sin HTTPS: van prácticamente en claro

CORS y la petición de comprobación previa

Por defecto el navegador aplica la política del mismo origen: el código de una página solo puede leer respuestas de su propio origen, entendido como la terna de esquema, dominio y puerto. CORS es el mecanismo con el que un servidor autoriza expresamente a que otro origen lea sus respuestas.

Para las peticiones que pueden tener efectos, el navegador no se arriesga: antes de mandarlas envía una petición de comprobación previa, el preflight, con el método OPTIONS. En ella anuncia qué método y qué cabeceras piensa usar, mediante Access-Control-Request-Method y Access-Control-Request-Headers. El servidor contesta con Access-Control-Allow-Origin, Access-Control-Allow-Methods y Access-Control-Allow-Headers, y solo si la respuesta autoriza lo pedido el navegador envía la petición de verdad.

http
OPTIONS /api/intentos HTTP/1.1
Origin: https://app.llegandoalcorte.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type


HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.llegandoalcorte.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: content-type
Access-Control-Max-Age: 600

Dos precisiones que se prestan a confusión. La autorización va por recurso, no por servidor entero. Y el rechazo no tiene un código propio: si el servidor no devuelve las cabeceras de autorización, la respuesta puede ser perfectamente un 200 y es el navegador quien bloquea el acceso al contenido. El 405 aparece en un caso distinto, cuando el servidor ni siquiera admite el método OPTIONS y por tanto el preflight no llega a responderse.

Para el examen

  • Qué bloquea la política del mismo origen: las peticiones entre orígenes distintos

  • Quién autoriza la excepción: el SERVIDOR, con Access-Control-Allow-Origin

  • Comprobación previa: va con el método OPTIONS

HSTS: obligar a ir siempre por HTTPS

Redirigir de HTTP a HTTPS con un 301 resuelve el caso normal pero deja una rendija: esa primera petición ha viajado en claro, y quien esté en medio de la red puede interceptarla antes de que llegue la redirección.

HSTS cierra esa rendija con la cabecera Strict-Transport-Security. Cuando el navegador la recibe, apunta durante el tiempo indicado en max-age que ese dominio solo se visita por HTTPS, y a partir de ese momento convierte internamente cualquier dirección http del sitio antes de enviar nada. El añadido includeSubDomains extiende la regla a todos los subdominios.

http
Strict-Transport-Security: max-age=31536000; includeSubDomains

El 301 es la redirección, no HSTS, y no es un error pese a lo que sugiere el nombre de la familia. HSTS es la cabecera que hace que la próxima vez ni siquiera haya que redirigir.

Para el examen

  • Qué es: una cabecera de respuesta

  • Qué obliga: a usar solo HTTPS en ese dominio durante el plazo indicado

  • Qué evita: el ataque de degradación a HTTP

CSP: de dónde puede cargar la página

La política de seguridad de contenido, o CSP, es más restrictiva y más fina que CORS, y ataca otro problema. CORS decide quién puede leer una respuesta; CSP decide de qué orígenes puede la propia página cargar cada tipo de recurso.

Se declara con la cabecera Content-Security-Policy, cuyo valor es una lista de directivas separadas por punto y coma. Cada directiva es un tipo de recurso terminado en -src, y a su lado van los orígenes permitidos: script-src para el código, style-src para las hojas de estilo, img-src para las imágenes, y default-src como valor de reserva para lo que no se haya nombrado.

http
Content-Security-Policy: default-src 'self'; script-src 'self'; img-src 'self' data:; style-src 'self'

Su utilidad principal es frenar el cross site scripting: si un atacante consigue inyectar una etiqueta de script que apunta a un servidor suyo, el navegador se niega a cargarla porque ese origen no está en la lista. La protección no depende de que el servidor haya filtrado bien la entrada.

Para el examen

  • Qué declara: de qué orígenes puede cargar la página guiones, estilos e imágenes

  • Contra qué protege: es la defensa de fondo frente al XSS