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

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 a la ligera. Los navegadores modernos ofrecen varios mecanismos que puedes usar para garantizar que los datos de tus usuarios estén seguros mientras están en tránsito: 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 sin encriptar.

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

Entregar una página web a través de una conexión HTTP sin encriptar es más o menos lo mismo que entregar un sobre sin sellar a la primera persona que ves en la calle que parece que camina en dirección a la oficina de correos. Si tienes suerte, puede que ella misma la lleve hasta allí o que se la entregue a la siguiente persona que vea que se dirige en la dirección correcta. Esa persona podría hacer lo mismo, y así sucesivamente.

La mayoría de los desconocidos de 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 con acceso completo a la carta que envías. Al final, es muy probable que el destinatario de tu carta reciba algo por correo, pero no se sabe si ese algo es lo mismo que entregaste en primer lugar. Tal vez deberías haber sellado ese sobre…

Intermediarios

Para bien o para mal, gran parte de Internet depende de la confiabilidad de desconocidos. Los servidores no están conectados directamente entre sí, sino que pasan solicitudes y respuestas de un router a otro en un juego enorme de teléfono descompuesto.

Puedes ver estos saltos en acción con traceroute. La ruta de mi computadora a HTML5Rocks se ve más o menos así:

$ 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

En realidad, 13 saltos no está mal. 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 sin encriptar, y cualquiera de esos intermediarios podría actuar como un intermediario, leyendo mis datos o incluso manipulándolos en tránsito.

Y lo que es peor, 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 garantizar que los datos recibidos sean _exactamente_ los datos enviados. Si alguien decide poner mi Internet patas arriba para divertirse, no tengo mucha suerte.

¿Es una línea segura?

Cambiar de HTTP de texto simple a una conexión HTTPS segura ofrece la mejor defensa contra los 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 bastantes detalles sobre el estado de una conexión.
El cuadro multifunción de Chrome proporciona bastantes 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. Por suerte, un análisis profundo de los detalles está 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 comprobando que el servidor tenga la clave privada adecuada. Toda la comunicación a partir de ese momento se encripta de tal manera que se demuestra que las solicitudes se entregan al servidor autenticado y que las respuestas se reciben de él.

Por lo tanto, HTTPS te brinda cierta seguridad de que te estás comunicando con el servidor que crees que es y de que nadie más está escuchando o modificando bits en la conexión. 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 (de forma gratuita) que te recomiendo que consultes para obtener detalles técnicos. La configuración variará según el proveedor y el servidor, pero el proceso de solicitud de certificado es el mismo en todos los casos.

Seguro de forma predeterminada

Una vez que hayas solicitado e instalado un certificado, asegúrate de que tus usuarios se beneficien de tu arduo trabajo: migra a tus 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/, redirecciónalo a https://example.com/ enviando una respuesta 301 Moved Permanently con un encabezado Location apropiado:

$ 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 brindarles a los usuarios experiencias de acceso sin interrupciones 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 con cada solicitud, lo que permite que el servidor determine a qué usuario está respondiendo en ese momento. Una vez que nos hayamos asegurado 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 en texto no encriptado.

Por lo general, la configuración de una cookie implica un encabezado HTTP similar al siguiente:

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 a las sesiones seguras 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.

Cerrando la ventana abierta

El redireccionamiento transparente a HTTPS significa que la gran mayoría del tiempo que tus usuarios estén en tu sitio, usarán una conexión segura. Sin embargo, deja una pequeña ventana de oportunidad para un ataque: la conexión HTTP inicial está completamente abierta y es vulnerable a la eliminación de SSL y a 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.

Puedes mitigar el riesgo de este tipo de ataque pidiéndole al navegador que aplique la Seguridad de transporte estricta de HTTP (HSTS). Cuando se envía el encabezado HTTP Strict-Transport-Security, se le indica al navegador que realice el redireccionamiento de HTTP a HTTPS del lado del cliente, sin tocar la red (esto también es excelente para el rendimiento; la mejor solicitud es la que no tienes que realizar):

$ 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) tomarán nota de que este sitio en particular solicitó acceso solo a HTTPS, lo que significa que, independientemente de cómo un usuario llegue 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), no se permitirá que los usuarios continúen a través de HTTP; es todo o nada, lo que es excelente.

El navegador hará que venza el estado de HSTS del servidor después de max-age segundos (aproximadamente 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 agregando 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

Avanza con seguridad

HTTPS es la única forma de tener una certeza, aunque sea remota, de que los datos que envías llegan intactos al destinatario previsto. Deberías configurar conexiones seguras para tus sitios y aplicaciones hoy mismo. Es un proceso bastante sencillo que ayudará a mantener seguros los datos de tus clientes. Una vez que hayas establecido un canal encriptado, debes redireccionar de forma transparente a los usuarios a esta conexión segura, independientemente de cómo lleguen a tu sitio, enviando 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 agregando la palabra clave secure cuando configures las cookies. Una vez que hayas hecho todo eso, asegúrate de que tus usuarios nunca se caigan del autobús por accidente: protégelos asegurándote de que su navegador haga lo correcto enviando 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 con verificación de dominio. No hay nada mejor que lo gratis. Por supuesto, es posible pasar a niveles más altos de verificación y el precio es razonable.
  • Prueba de servidor SSL: Una vez que hayas configurado HTTPS para tus servidores, verifica que lo hayas hecho correctamente ejecutando la prueba de servidor de SSL Labs. Obtendrás un informe bien detallado que te mostrará si realmente estás en funcionamiento.
  • Vale la pena leer el artículo reciente de Ars Technica "Securing your Web Server with SSL/TLS" para obtener un poco más de información sobre los aspectos básicos de la configuración de un servidor.
  • Vale la pena leer la especificación de HTTP con Seguridad de Transporte Estricta (RFC6797) para obtener toda la información técnica que puedas desear sobre el encabezado Strict-Transport-Security.
  • Una vez que sepas realmente lo que estás haciendo, un posible paso siguiente sería anunciar que solo se debe poder acceder a tu sitio a través de un conjunto específico de certificados. Se está trabajando en el IETF para que puedas hacerlo a través del encabezado Public-Key-Pins. Aún es pronto, pero es interesante y vale la pena seguirlo.