Una introducción rápida a la seguridad web.

¡Un manual para desarrolladores web sobre CORS, CSP, HSTS y todas las siglas de seguridad web!

Foto de Jose Fontano en Unsplash

Hay muchas razones para aprender sobre seguridad web, como:

  • Usted es un usuario preocupado que está preocupado por la filtración de sus datos personales.
  • Eres un desarrollador web preocupado que quiere hacer que sus aplicaciones web sean más seguras
  • Usted es un desarrollador web que solicita empleo y desea estar listo si sus entrevistadores le hacen preguntas sobre seguridad web

y así.

Bueno, esta publicación explicará algunos acrónimos comunes de seguridad web de una manera fácil de entender pero precisa.

Antes de hacer eso, asegurémonos de comprender algunos conceptos básicos de seguridad.

Dos conceptos básicos de seguridad

Nadie es 100% seguro.

No existe la noción de estar 100% protegido de ser pirateado. Si alguien te dice eso, está equivocado.

Una capa de protección no es suficiente.

No puedes simplemente decir ...

Oh, porque tengo CSP implementado, estoy a salvo. Puedo tachar las secuencias de comandos entre sitios de mi lista de vulnerabilidades porque eso no puede suceder ahora.

Tal vez eso sea un hecho para algunos, pero es fácil encontrarse pensando de esta manera. Creo que una de las razones por las que los programadores pueden encontrarse fácilmente pensando de esta manera es porque gran parte de la codificación es en blanco y negro, 0 o 1, verdadero o falso. La seguridad no es tan simple.

Comenzaremos con uno con el que todos se encuentren bastante temprano en su viaje de desarrollo web. Y luego buscas en StackOverflow y encuentras un montón de respuestas que te dicen cómo evitarlo.

Intercambio de recursos de origen cruzado (CORS)

¿Alguna vez has recibido un error que se parece a esto?

No hay encabezado 'Access-Control-Allow-Origin' presente en el recurso solicitado. Por lo tanto, el origen 'nulo' no tiene acceso permitido.

Ciertamente no estás solo. Y luego lo buscas en Google, ¡y alguien te dice que obtengas esta extensión que hará que todos tus problemas desaparezcan!

Genial, verdad?

¡CORS está ahí para protegerte, no para lastimarte!

Para explicar cómo CORS lo ayuda, primero hablemos sobre las cookies, específicamente las cookies de autenticación. Las cookies de autenticación se utilizan para decirle a un servidor que ha iniciado sesión, y se envían automáticamente con cualquier solicitud que realice a ese servidor.

Supongamos que ha iniciado sesión en Facebook y utilizan cookies de autenticación. Hace clic en bit.ly/r43nugi que lo redirige a superevilwebsite.rocks. ¡Un script dentro de superevilwebsite.rocks realiza una solicitud del lado del cliente a facebook.com que envía su cookie de autenticación!

En un mundo sin CORS, podrían hacer cambios en su cuenta sin que usted lo sepa. Hasta que, por supuesto, publiquen bit.ly/r43nugi en su línea de tiempo, y todos sus amigos hagan clic en él, y luego publiquen bit.ly/r43nugi en todas las líneas de tiempo de sus amigos y luego el ciclo continúe en una amplitud maligna -primer esquema que conquista a todos los usuarios de Facebook, y el mundo es consumido por superevilwebsite.rocks.

Sin embargo, en un mundo CORS, Facebook solo permitiría solicitudes con un origen de facebook.com para editar datos en su servidor. En otras palabras, limitarían el intercambio de recursos de origen cruzado. Entonces podrías preguntar ...

¿Puede superevilwebsite.rocks simplemente cambiar el encabezado de origen en su solicitud, para que parezca que proviene de facebook.com?

Pueden intentarlo, pero no funcionará porque el navegador simplemente lo ignorará y usará el origen real.

Ok, pero ¿qué pasa si superevilwebsite.rocks hizo la solicitud del lado del servidor?

En este caso, podrían omitir CORS, pero no ganarán porque no podrán enviar su cookie de autenticación para el viaje. El script debería ejecutarse en el lado del cliente para obtener acceso a las cookies del lado del cliente.

Política de seguridad de contenido (CSP)

Para comprender CSP, primero tenemos que hablar sobre una de las vulnerabilidades más comunes en la web: XSS, que significa scripting entre sitios (sí, otro acrónimo).

XSS es cuando una persona malvada inyecta JavaScript en su código del lado del cliente. Tú puedes pensar…

Qué van a hacer? ¿Cambiar un color de rojo a azul?

Supongamos que alguien ha inyectado JavaScript correctamente en el código del lado del cliente de un sitio web que está visitando.

¿Qué podrían hacer que fuera malicioso?

  • Podrían hacer solicitudes HTTP a otro sitio haciéndose pasar por usted.
  • Podrían agregar una etiqueta de anclaje que lo envíe a un sitio web que se vea idéntico al que tiene con algunas características maliciosas ligeramente diferentes.
  • Podrían agregar una etiqueta de script con JavaScript en línea.
  • Podrían agregar una etiqueta de script que recupere un archivo remoto de JavaScript en alguna parte.
  • Podrían agregar un iframe que cubra la página y se vea como parte del sitio web solicitándole que inserte su contraseña.

Las posibilidades son infinitas.

CSP intenta evitar que esto suceda limitando:

  • ¿Qué se puede abrir en un iframe?
  • qué hojas de estilo se pueden cargar
  • donde se pueden hacer solicitudes, etc.

¿Entonces, cómo funciona?

Cuando hace clic en un enlace o escribe la URL de un sitio web en la barra de direcciones de su navegador, su navegador realiza una solicitud GET. Eventualmente llega a un servidor que sirve HTML junto con algunos encabezados HTTP. Si tiene curiosidad acerca de qué encabezados recibe, abra la pestaña Red en su consola y visite algunos sitios web.

Es posible que vea un encabezado de respuesta similar a este:

content-security-policy: default-src * data: blob:; script-src * .facebook.com * .fbcdn.net * .facebook.net * .google-analytics.com * .virtualearth.net * .google.com 127.0.0.1:* * .spotilocal.com: * 'unsafe-inline' 'unsafe-eval' * .atlassolutions.com blob: data: 'self'; style-src data: blob: 'unsafe-inline' *; connect -src * .facebook.com facebook.com * .fbcdn.net * .facebook.net * .spotilocal.com: * wss: //*.facebook.com: * https://fb.scanandcleanlocal.com:* * .atlassolutions.com attach.fbsbx.com ws: // localhost: * blob: * .cdninstagram.com 'self' chrome-extension: // boadgeojelhgndaghljhdicfkmllpafd chrome-extension: // dliochdbjfkdbacpmhlcpmleaejidimm;

Esa es la política de seguridad de contenido de facebook.com. Vuelva a formatearlo para que sea más fácil de leer:

política de seguridad de contenido:
default-src * data: blob :;
script-src * .facebook.com * .fbcdn.net * .facebook.net * .google-analytics.com * .virtualearth.net * .google.com 127.0.0.1:* * .spotilocal.com: * 'inseguro- en línea '' unsafe-eval '* .atlassolutions.com blob: data:' self ';
datos style-src: blob: 'inseguro en línea' *;
connect-src * .facebook.com facebook.com * .fbcdn.net * .facebook.net * .spotilocal.com: * wss: //*.facebook.com: * https://fb.scanandcleanlocal.com:* * .atlassolutions.com attach.fbsbx.com ws: // localhost: * blob: * .cdninstagram.com 'self' chrome-extension: // boadgeojelhgndaghljhdicfkmllpafd chrome-extension: // dliochdbjfkdbacpmhlcpmleaejidimm;

Ahora, analicemos las directivas.

  • default-src restringe todas las demás directivas CSP que no se enumeran explícitamente.
  • script-src restringe los scripts que se pueden cargar.
  • style-src restringe las hojas de estilo que se pueden cargar.
  • connect-src restringe las URL que se pueden cargar mediante interfaces de script, por lo que fetch, XHR, ajax, etc.

Tenga en cuenta que hay muchas más directivas CSP que solo estas cuatro que se muestran arriba. El navegador leerá el encabezado CSP y aplicará esas directivas a todo el contenido del archivo HTML que se sirvió. Si las directivas se establecen adecuadamente, solo permiten lo necesario.

Si no hay un encabezado CSP, entonces todo funciona y nada está restringido. Donde quiera que veas *, eso es un comodín. Puedes imaginar reemplazar * con cualquier cosa y se permitirá.

HTTPS o HTTP seguro

Ciertamente has oído hablar de HTTPS. Tal vez has escuchado a algunas personas decir ...

¿Por qué me importa usar HTTPS si solo estoy en un sitio web jugando un juego?

O tal vez has escuchado el otro lado ...

Estás loco si tu sitio no tiene HTTPS. ¡Es 2018! No confíes en nadie que diga lo contrario.

Tal vez escuchaste que Chrome ahora marcará tu sitio como inseguro si no es HTTPS.

En esencia, HTTPS es bastante sencillo. HTTPS está encriptado y HTTP no.

Entonces, ¿por qué importa esto si no envía datos confidenciales?

Prepárese para otro acrónimo ... MITM, que significa Hombre en el Medio.

Si está utilizando Wi-Fi público sin contraseña en una cafetería, es bastante fácil que alguien actúe como su enrutador, de modo que todas las solicitudes y respuestas pasen por ellos. Si sus datos no están encriptados, pueden hacer lo que quieran con ellos. Pueden editar el HTML, CSS o JavaScript incluso antes de que llegue a su navegador. Dado lo que sabemos sobre XSS, puedes imaginar lo malo que podría ser.

Ok, pero ¿cómo es que mi computadora y el servidor saben cifrar / descifrar pero este MITM no?

Ahí es donde entra en juego SSL (Secure Sockets Layer) y más recientemente, TLS (Transport Layer Security). TLS se hizo cargo de SSL en 1999 como la tecnología de cifrado utilizada en HTTPS. Exactamente cómo funciona TLS está fuera del alcance de esta publicación.

Seguridad estricta de transporte HTTP (HSTS)

Este es bastante sencillo. Usemos nuevamente el encabezado de Facebook como ejemplo:

seguridad de transporte estricta: edad máxima = 15552000; precargar
  • max-age especifica cuánto tiempo debe recordar un navegador forzar al usuario a acceder a un sitio web utilizando HTTPS.
  • La precarga no es importante para nuestros propósitos. Es un servicio alojado por Google y no forma parte de la especificación HSTS.

Este encabezado solo se aplica si accedió al sitio usando HTTPS. Si accedió al sitio a través de HTTP, se ignora el encabezado. La razón es que, simplemente, HTTP es tan inseguro que no se puede confiar.

Usemos el ejemplo de Facebook para ilustrar mejor cómo esto es útil en la práctica. Está accediendo a facebook.com por primera vez y sabe que HTTPS es más seguro que HTTP, por lo que accede a través de HTTPS, https://facebook.com. Cuando su navegador recibe el HTML, recibe el encabezado anterior que le indica a su navegador que lo obligue a redirigirlo a HTTPS para futuras solicitudes. Un mes después, alguien le envía un enlace a Facebook usando HTTP, http://facebook.com, y usted hace clic en él. Como un mes es inferior a los 15552000 segundos especificados por la directiva de edad máxima, su navegador enviará la solicitud como HTTPS, evitando un posible ataque MITM.

Pensamientos finales

La seguridad web es importante sin importar dónde se encuentre en su viaje de desarrollo web. Cuanto más te expongas a ella, mejor estarás. ¡La seguridad es algo que debería ser importante para todos, no solo para las personas que lo mencionan explícitamente en el título de su trabajo!