Blog personal de Diego de Haller
Blog personal de Diego de Haller

Haciendo un blog más seguro – Content Security Policy

 

Hoy en día la seguridad mientras navegamos es no ya importante, es crucial. Cada vez recibimos más mensajes con phishing donde servicios de renombre como Paypal, WordPress, Yahoo y otros nos piden que confirmemos nuestros. Nótese que pongo piden en cursiva, puesto que realmente no son ellos, pero los malos que intentan engañarnos. Generalmente es fácil de detectar: las direcciones web que utilizan no son las de los servicios en cuestión, se parecen, pero no son las legítimas.

Otro tipo de ataque que podemos recibir es de alguien que consigue acceder a un servidor para poner un código malicioso en la página web. Imaginaos este escenario: una tienda online tiene su servidor pirateado (sin saberlo los dueños) y en la página en la que se piden los datos de la tarjeta de crédito para hacer el pago, el formulario no envía los datos sólo al comercio, también los envía al pirata. Ya podéis ver el resultado, ¿verdad?

¿Cómo evitar eso?

No hay métodos 100% infalibles, pero está claro que podemos ponerle las cosas muy díficiles al pirata. Una manera es usando Content Security Policy (CSP) o Reglas de seguridad de contenido. Consiste en definir reglas, a nivel del servidor web, para definir qué URLs se pueden servir, tanto para las páginas, como para las imágines, scripts y un largo etcétera. De esta manera, podríamos definir una regla que diga que sólo autorizamos que el servidor ejecute código que proviene de nuestro propio servidor, de directorios concretos. O que permita mostrar páginas que se han generado mediante un código que está en otro servidor (Google o Facebook).

Si os fijáis en todo lo que carga una página cuando la visitáis, os quedaríais sorprendidos, no ya por la cantidad, pero por el origen. Por ejemplo, este blog:

containBlog

Como véis, no sólo carga del dominio diego.dehaller.ch, también de Gravatar (para los avatares de los comentaristas), de WordPress (para servicios de stats y otros), de Google (para las fuentes true type) y de otros.

Por ello, si ponemos una regla CSP que dice que sólo podremos servir páginas que se han generado en nuestro dominio, la mitad del blog no funcionaría. Así que tenemos que ir probando. Afortunadamente, hay un servicio llamado Report URI que nos ayuda bastante para analizar los bloqueos generados y también crear nuestras reglas CSP. Creado por Scott Helme, en cuyo blog podréis encontrar muchas explicaciones sobre CSP y otras medidas de seguridad, este servicio guarda los logs de los bloqueos que se han hecho con nuestras reglas CSP para poder analizarlas y hacer las correcciones necesarias.

CSP Reports

Una buena práctica, para no tener que ir haciendo prueba-error y durante dicho proceso bloquear el acceso a nuestra web, es usar CSP en modo report-only, de manera que tenemos los logs de lo que nuestras reglas CSP bloquearían pero sin bloquear realmente las cosas.

Bien, con esta introducción sobre CSP (insisto en que podéis aprender más sobre ello en el blog de Scott), paso a detallar qué es lo que he hecho para crear unas reglas CSP que hagan más seguro mi blog sin evitar que funcione correctamente. Aquí hago un inciso: no os recomiendo copiar y pegar las reglas que uso para vuestro blog, puesto que cada uno tendrá diferentes orígenes. Seguro que en parte funcionará, pero no todo. Así que os recomiendo que analicéis bien y vayáis desbloqueando poco a poco. Usad primero CSP en modo report-only, para que así vuestro blog no se quede cojo durante el proceso.

He aquí mis reglas CSP:

Content-Security-Policy: "default-src 'self' 'unsafe-inline' gmpg.org *.wp.com secure.gravatar.com fonts.googleapis.com s.w.org; script-src 'self' 'unsafe-inline' 'unsafe-eval' gmpg.org *.wp.com secure.gravatar.com fonts.googleapis.com s.w.org ajax.cloudflare.com diegodehaller.disqus.com maps.google.com maps.googleapis.com api.pinterest.com graph.facebook.com public-api.wordpress.com; style-src 'self' 'unsafe-inline' gmpg.org *.wp.com secure.gravatar.com fonts.googleapis.com s.w.org a.disquscdn.com; img-src 'self' gmpg.org *.wp.com secure.gravatar.com fonts.googleapis.com s.w.org csi.gstatic.com maps.googleapis.com referrer.disqus.com a.disquscdn.com res.cloudinary.com s0.wordpress.com data; font-src 'self' data: gmpg.org *.wp.com secure.gravatar.com fonts.googleapis.com s.w.org fonts.gstatic.com; connect-src *; media-src *; object-src *; child-src *; frame-src *; worker-src *; frame-ancestors 'none'; report-uri https://dehaller.report-uri.io/r/default/csp/enforce;"

¿Pero cómo he llegado a eso? Pues poco a poco, con la ayuda de Reports URI y su generador de reglas CSP:

Generate CSP

Os recomiendo empezar poniendo para los puntos 1, 2, 3, 4 y 5 ‘self’, para que os quede algo como esto:

Content-Security-Policy-Report-Only:: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; report-to reportsuri;

Cuando visitéis vuestra página, veréis que todo va bien, pero viendo los informes de Report URI, veréis que bloquea ciertas cosas. No tenéis más que ir añadiéndolo al generador, como por ejemplo:

CSP Generator

Y así hasta que vuestro log esté vacío. Cuando sea el caso, no tenéis más que activar las reglas, quitando el modo report-only, y os quedará una cosa tal como os puse antes.

Y muchos os preguntaréis: ¿dónde tengo que poner este chorizo que he generado? Pues depende del servidor que tengáis. Yo lo he hecho para un servidor Apache, pero para otros como IIS o Ngynx también existe. En Apache, todo está en el fichero httpd.conf, donde pondréis esto:

Header set

y detrás el chorizo:

Content-Security-Policy: "default-src 'self' 'unsafe-inline' gmpg.org *.wp.com secure.gravatar.com fonts.googleapis.com s.w.org; script-src 'self' 'unsafe-inline' 'unsafe-eval' gmpg.org *.wp.com secure.gravatar.com fonts.googleapis.com s.w.org ajax.cloudflare.com diegodehaller.disqus.com maps.google.com maps.googleapis.com api.pinterest.com graph.facebook.com public-api.wordpress.com; style-src 'self' 'unsafe-inline' gmpg.org *.wp.com secure.gravatar.com fonts.googleapis.com s.w.org a.disquscdn.com; img-src 'self' gmpg.org *.wp.com secure.gravatar.com fonts.googleapis.com s.w.org csi.gstatic.com maps.googleapis.com referrer.disqus.com a.disquscdn.com res.cloudinary.com s0.wordpress.com data; font-src 'self' data: gmpg.org *.wp.com secure.gravatar.com fonts.googleapis.com s.w.org fonts.gstatic.com; connect-src *; media-src *; object-src *; child-src *; frame-src *; worker-src *; frame-ancestors 'none'; report-uri https://dehaller.report-uri.io/r/default/csp/enforce;"

Reiniciáis Apache, y a probar. Tendréis que tener mucha paciencia, probar con varios navegadores – sí amigos, sí, aquí tenemos el mismo problema que con el código HTML, que depende del navegador veremos una cosa u otra – y, si no tenéis dispositivos de varias marcas/modelos, pedir ayuda – como hice yo con Julen (gracias de nuevo).

Como decía al principio, todo es esto hará que sea más difícil que un pirata pueda aprovecharse de vuestro blog para meter su propio código. Una cosa que tendréis que tener en cuenta es que si consigue un acceso completo al servidor, podrá quitar las reglas CSP en menos de 30 segundos. O si consigue modificar código del blog, tampoco valdrá de mucho. Pero como digo, complica las cosas un poco más.

¡Saludos!