Confunde a los intermediarios maliciosos con HTTPS y HTTP con seguridad de transporte estricta

Dada la cantidad de datos personales que fluyen a través de la gran serie de tubos que es Internet, la encriptación no es algo que podamos o debamos ignorar. Los navegadores modernos ofrecen varios mecanismos que puedes usar para asegurarte de que los datos de tus usuarios estén protegidos durante el envío: las cookies seguras y la seguridad de transporte estricta son dos de los más importantes. Te permiten proteger a tus usuarios sin problemas, actualizar sus conexiones a HTTPS y garantizar que los datos de los usuarios nunca se envíen de forma no encriptada.

¿Por qué debería interesarte? Considera lo siguiente:

Entregar una página web a través de una conexión HTTP no encriptada es más o menos lo mismo que entregar un sobre sin sellar a la primera persona que veas en la calle que parezca que camina en dirección a la oficina de correos. Si tienes suerte, podría llevarte hasta allí o entregarte el paquete a la próxima persona que vea que va en la dirección correcta. Esa persona podría hacer lo mismo, y así sucesivamente.

La mayoría de los extraños en esta cadena improvisada son confiables y nunca mirarían tu carta abierta ni la alterarían. Sin embargo, cuantas más veces cambie de manos la carta, mayor será la cantidad de personas que tendrán acceso completo a la carta que envías. Al final, es muy probable que el destinatario de tu carta reciba algo por correo, pero si ese algo es el mismo que entregaste en primer lugar es una pregunta abierta. Tal vez deberías haber sellado ese sobre…

Intermediarios

Para bien o para mal, grandes porciones de Internet dependen de la confiabilidad de los extraños. Los servidores no están conectados directamente entre sí, sino que pasan solicitudes y respuestas de un router a otro en un enorme juego de teléfono descompuesto.

Puedes ver estos saltos en acción con traceroute. La ruta de mi computadora a HTML5Rocks se ve de la siguiente manera:

$ traceroute html5rocks.com
traceroute to html5rocks.com (173.194.71.102), 30 hops max, 60 byte packets
 1  router1-lon.linode.com (212.111.33.229)  0.453 ms
 2  212.111.33.233 (212.111.33.233)  1.067 ms
 3  217.20.44.194 (217.20.44.194)  0.704 ms
 4  google1.lonap.net (193.203.5.136)  0.804 ms
 5  209.85.255.76 (209.85.255.76)  0.925 ms
 6  209.85.253.94 (209.85.253.94)  1.226 ms
 7  209.85.240.28 (209.85.240.28)  48.714 ms
 8  216.239.47.12 (216.239.47.12)  22.575 ms
 9  209.85.241.193 (209.85.241.193)  36.033 ms
10  72.14.233.180 (72.14.233.180)  43.222 ms
11  72.14.233.170 (72.14.233.170)  43.242 ms
12  *
13  lb-in-f102.1e100.net (173.194.71.102)  44.523 ms

13 saltos no es tan malo. Sin embargo, si envío solicitudes a través de HTTP, cada uno de esos routers intermedios tiene acceso completo a mis solicitudes y a las respuestas de los servidores. Todos los datos se transfieren como texto simple no encriptado, y cualquiera de esos intermediarios podría actuar como un hombre en el medio, leyendo mis datos o incluso manipulándolos en tránsito.

Peor aún, este tipo de intercepción es prácticamente indetectable. Una respuesta HTTP modificada de forma maliciosa se ve exactamente como una respuesta válida, ya que no existe ningún mecanismo que te permita asegurarte de que los datos recibidos sean _exactamente_ los datos enviados. Si alguien decide cambiar mi conexión a Internet por diversión, no tengo suerte.

¿Es una línea segura?

Cambiar de HTTP de texto simple a una conexión HTTPS segura ofrece la mejor defensa contra intermediarios. Las conexiones HTTPS encriptan todo el canal de extremo a extremo antes de que se envíen los datos, lo que hace imposible que las máquinas entre tú y tu destino lean o modifiquen los datos en tránsito.

El cuadro multifunción de Chrome proporciona muchos detalles sobre el estado de una conexión.
El cuadro multifunción de Chrome proporciona muchos detalles sobre el estado de una conexión.

La seguridad que proporciona HTTPS se basa en el concepto de claves criptográficas públicas y privadas. Una discusión detallada de los detalles (por suerte) está muy por fuera del alcance de este artículo, pero la premisa principal es bastante sencilla: los datos encriptados con una clave pública determinada solo se pueden desencriptar con la clave privada correspondiente. Cuando un navegador inicia un protocolo de enlace HTTPS para crear un canal seguro, el servidor proporciona un certificado que le brinda al navegador toda la información necesaria para verificar su identidad, ya que comprueba que el servidor tenga la clave privada adecuada. A partir de ese punto, toda la comunicación se encripta de manera tal que se demuestre que las solicitudes se entregan y las respuestas se reciben del servidor autenticado.

Por lo tanto, HTTPS te brinda cierta seguridad de que estás hablando con el servidor con el que crees que estás hablando y de que nadie más está escuchando o manipulando bits en el cable. Este tipo de encriptación es un requisito previo absoluto para la seguridad en la Web. Si tu aplicación no se entrega actualmente a través de HTTPS, es vulnerable a ataques. Soluciónalo Ars Technica tiene una excelente guía para obtener e instalar un certificado (gratis) que te recomiendo consultar para obtener detalles técnicos. La configuración diferirá de un proveedor a otro y de un servidor a otro, pero el proceso de solicitud de certificado es el mismo en todas partes.

Segura de forma predeterminada

Una vez que hayas solicitado e instalado un certificado, asegúrate de que los usuarios se beneficien de tu arduo trabajo: migra a los usuarios existentes a conexiones HTTPS de forma transparente a través de la magia del redireccionamiento HTTP y asegúrate de que las cookies se entreguen solo a través de conexiones seguras.

Por aquí, por favor

Cuando un usuario visite http://example.com/, redirecciona a https://example.com/ enviándole una respuesta 301 Moved Permanently con un encabezado Location adecuado:

$ curl -I http://mkw.st/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.3.7
...
Keep-Alive: timeout=20
Location: https://mkw.st/

Puedes configurar este tipo de redireccionamiento fácilmente en servidores como Apache o Nginx. Por ejemplo, una configuración de Nginx que redirecciona de http://example.com/ a https://example.com/ se ve de la siguiente manera:

server {
    listen [YOUR IP ADDRESS HERE]:80;
    server_name example.com www.example.com;
    location "/" {
        rewrite ^(.*) https://www.example.com$1 permanent;
    }
}

Las cookies nos permiten proporcionar a los usuarios experiencias de acceso fluidas a través del protocolo HTTP sin estado. Los datos almacenados en las cookies, incluida la información sensible, como los IDs de sesión, se envían junto con cada solicitud, lo que permite que el servidor comprenda a qué usuario le está respondiendo en ese momento. Una vez que nos aseguremos de que los usuarios accedan a nuestro sitio a través de HTTPS, también debemos asegurarnos de que los datos sensibles almacenados en las cookies solo se transfieran a través de una conexión segura y nunca se envíen de forma no encriptada.

La configuración de una cookie suele implicar un encabezado HTTP que se ve de la siguiente manera:

set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT

Puedes indicarle al navegador que restrinja el uso de la cookie para proteger las sesiones agregando una sola palabra clave:

Set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT; secure

Las cookies configuradas con la palabra clave secure nunca se enviarán a través de HTTP.

Cerrar la ventana abierta

El redireccionamiento transparente a HTTPS significa que, la gran mayoría de las veces que los usuarios están en tu sitio, usarán una conexión segura. Sin embargo, deja una pequeña ventana de oportunidad para el ataque: la conexión HTTP inicial está completamente abierta y es vulnerable a la eliminación de SSL y a los ataques relacionados. Dado que un intermediario tiene acceso completo a la solicitud HTTP inicial, puede actuar como proxy entre tú y el servidor, lo que te mantiene en una conexión HTTP no segura, independientemente de las intenciones del servidor.

Para mitigar el riesgo de este tipo de ataque, pídele al navegador que aplique la seguridad de transporte estricta (HSTS) de HTTP. El envío del encabezado HTTP Strict-Transport-Security le indica al navegador que realice el redireccionamiento de HTTP a HTTPS del cliente, sin tocar la red (esto también es excelente para el rendimiento; la mejor solicitud es la que no tienes que hacer):

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

Los navegadores que admiten este encabezado (actualmente, Firefox, Chrome y Opera: caniuse tiene detalles) harán una nota que indique que este sitio en particular solicitó acceso solo a HTTPS, lo que significa que, independientemente de cómo llegue un usuario al sitio, lo visitará a través de HTTPS. Incluso si escribe http://example.com/ en el navegador, terminará en HTTPS sin establecer una conexión HTTP. Mejor aún, si el navegador detecta un certificado no válido (que podría intentar falsificar la identidad de tu servidor), los usuarios no podrán continuar a través de HTTP. Es todo o nada, lo cual es excelente.

El navegador vencerá el estado de HSTS del servidor después de max-age segundos (alrededor de un mes en este ejemplo). Establece un valor razonablemente alto.

También puedes asegurarte de que todos los subdominios de un origen estén protegidos si agregas la directiva includeSubDomains al encabezado:

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

Continúa de forma segura

HTTPS es la única forma de garantizar, aunque sea de forma remota, que los datos que envíes lleguen intactos al destinatario previsto. Debes configurar conexiones seguras para tus sitios y aplicaciones hoy mismo. Es un proceso bastante sencillo y ayudará a proteger los datos de tus clientes. Una vez que tengas un canal encriptado, debes redireccionar a los usuarios de forma transparente a esta conexión segura, independientemente de cómo lleguen a tu sitio, mediante el envío de una respuesta HTTP 301. Luego, asegúrate de que toda la información sensible de la sesión de tus usuarios use solo esa conexión segura. Para ello, agrega la palabra clave secure cuando configures las cookies. Una vez que hayas hecho todo eso, asegúrate de que tus usuarios nunca se queden sin servicio por accidente: protégelos asegurándote de que su navegador haga lo correcto y envíe un encabezado Strict-Transport-Security.

Configurar HTTPS no requiere mucho trabajo y tiene grandes beneficios para tu sitio y sus usuarios. Vale la pena el esfuerzo.

Recursos

  • StartSSL ofrece certificados gratuitos verificados por dominio. No puedes superar lo gratis. Por supuesto, es posible obtener grados de verificación más altos a precios razonables.
  • Prueba del servidor SSL: Una vez que hayas configurado HTTPS para tus servidores, verifica que lo hayas hecho correctamente ejecutándolo a través de la prueba del servidor de SSL Labs. Recibirás un informe detallado que te mostrará si realmente estás en funcionamiento.
  • Te recomendamos que leas el artículo reciente de Ars Technica "Cómo proteger tu servidor web con SSL/TLS" para obtener más detalles sobre los aspectos básicos de la configuración de un servidor.
  • Vale la pena consultar la especificación de seguridad de transporte estricta de HTTP (RFC6797) para obtener toda la información técnica que puedas necesitar sobre el encabezado Strict-Transport-Security.
  • Una vez que sepas realmente lo que estás haciendo, un posible paso a seguir sería anunciar que solo se puede acceder a tu sitio a través de un conjunto específico de certificados. En el IETF, se está trabajando en un proyecto que te permitiría hacer precisamente eso a través del encabezado Public-Key-Pins. Aún es un tema en desarrollo, pero es interesante y vale la pena seguirle el rastro.