{"id":19007,"date":"2017-01-04T10:22:58","date_gmt":"2017-01-04T09:22:58","guid":{"rendered":"https:\/\/diego.dehaller.ch\/blog\/?p=19007"},"modified":"2020-05-18T02:14:17","modified_gmt":"2020-05-18T00:14:17","slug":"haciendo-un-blog-mas-seguro-content-security-policy","status":"publish","type":"post","link":"https:\/\/diego.dehaller.ch\/blog\/2017\/haciendo-un-blog-mas-seguro-content-security-policy.html","title":{"rendered":"Haciendo un blog m\u00e1s seguro &#8211; Content Security Policy"},"content":{"rendered":"<p>&nbsp;<\/p>\n<p>Hoy en d\u00eda la seguridad mientras navegamos es no ya importante, es crucial. Cada vez recibimos m\u00e1s mensajes con phishing donde servicios de renombre como Paypal, WordPress, Yahoo y otros nos <em>piden<\/em> que confirmemos nuestros. N\u00f3tese que pongo piden en cursiva, puesto que realmente no son ellos, pero los <em>malos<\/em> que intentan enga\u00f1arnos. Generalmente es f\u00e1cil de detectar: las direcciones web que utilizan no son las de los servicios en cuesti\u00f3n, se parecen, pero no son las leg\u00edtimas.<\/p>\n<p>Otro tipo de ataque que podemos recibir es de alguien que consigue acceder a un servidor para poner un c\u00f3digo malicioso en la p\u00e1gina web. Imaginaos este escenario: una tienda online tiene su servidor pirateado (sin saberlo los due\u00f1os) y en la p\u00e1gina en la que se piden los datos de la tarjeta de cr\u00e9dito para hacer el pago, el formulario no env\u00eda los datos s\u00f3lo al comercio, tambi\u00e9n los env\u00eda al pirata. Ya pod\u00e9is ver el resultado, \u00bfverdad?<\/p>\n<h3>\u00bfC\u00f3mo evitar eso?<\/h3>\n<p>No hay m\u00e9todos 100% infalibles, pero est\u00e1 claro que podemos ponerle las cosas muy d\u00edficiles 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\u00e9 URLs se pueden servir, tanto para las p\u00e1ginas, como para las im\u00e1gines, scripts y un largo etc\u00e9tera. De esta manera, podr\u00edamos definir una regla que diga que s\u00f3lo autorizamos que el servidor ejecute c\u00f3digo que proviene de nuestro propio servidor, de directorios concretos. O que permita mostrar p\u00e1ginas que se han generado mediante un c\u00f3digo que est\u00e1 en otro servidor (Google o Facebook).<\/p>\n<p>Si os fij\u00e1is en todo lo que carga una p\u00e1gina cuando la visit\u00e1is, os quedar\u00edais sorprendidos, no ya por la cantidad, pero por el origen. Por ejemplo, este blog:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-19011\" title=\"containBlog\" src=\"https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_13_37_33-Diego_Blog_Blog_personal_de_Diego_de_Haller_qxpasd-500x442.jpg\" alt=\"containBlog\" width=\"960\" height=\"849\" srcset=\"https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_13_37_33-Diego_Blog_Blog_personal_de_Diego_de_Haller_qxpasd-500x442.jpg 500w, https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_13_37_33-Diego_Blog_Blog_personal_de_Diego_de_Haller_qxpasd-768x679.jpg 768w, https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_13_37_33-Diego_Blog_Blog_personal_de_Diego_de_Haller_qxpasd-570x504.jpg 570w, https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_13_37_33-Diego_Blog_Blog_personal_de_Diego_de_Haller_qxpasd.jpg 960w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" \/><\/p>\n<p>Como v\u00e9is, no s\u00f3lo carga del dominio diego.dehaller.ch, tambi\u00e9n 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.<\/p>\n<p>Por ello, si ponemos una regla CSP que dice que s\u00f3lo podremos servir p\u00e1ginas que se han generado en nuestro dominio, la mitad del blog no funcionar\u00eda. As\u00ed que tenemos que ir probando. Afortunadamente, hay un servicio llamado <a href=\"https:\/\/report-uri.io\/\">Report URI<\/a> que nos ayuda bastante para analizar los bloqueos generados y tambi\u00e9n crear nuestras reglas CSP. Creado por <a href=\"https:\/\/scotthelme.co.uk\/\">Scott Helme<\/a>, en cuyo blog podr\u00e9is encontrar <a href=\"https:\/\/scotthelme.co.uk\/content-security-policy-an-introduction\/\">muchas explicaciones sobre CSP<\/a> 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.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-19013\" title=\"CSP Reports\" src=\"https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_13_44_49-_dunrk6.jpg\" alt=\"CSP Reports\" width=\"960\" height=\"506\" srcset=\"https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_13_44_49-_dunrk6.jpg 960w, https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_13_44_49-_dunrk6-500x264.jpg 500w, https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_13_44_49-_dunrk6-768x405.jpg 768w, https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_13_44_49-_dunrk6-570x300.jpg 570w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" \/><\/p>\n<p>Una buena pr\u00e1ctica, 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\u00edan pero sin bloquear realmente las cosas.<\/p>\n<p>Bien, con esta introducci\u00f3n sobre CSP (insisto en que pod\u00e9is aprender m\u00e1s sobre ello en el blog de Scott), paso a detallar qu\u00e9 es lo que he hecho para crear unas reglas CSP que hagan m\u00e1s seguro mi blog sin evitar que funcione correctamente. <strong>Aqu\u00ed hago un inciso: no os recomiendo copiar y pegar las reglas que uso para vuestro blog, puesto que cada uno tendr\u00e1 diferentes or\u00edgenes. Seguro que en parte funcionar\u00e1, pero no todo<\/strong>. As\u00ed que os recomiendo que analic\u00e9is bien y vay\u00e1is desbloqueando poco a poco. Usad primero CSP en modo report-only, para que as\u00ed vuestro blog no se quede cojo durante el proceso.<\/p>\n<p>He aqu\u00ed mis reglas CSP:<\/p>\n<p><code>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;\"<\/code><\/p>\n<p>\u00bfPero c\u00f3mo he llegado a eso? Pues poco a poco, con la ayuda de Reports URI y su <a href=\"https:\/\/report-uri.io\/home\/generate\" target=\"_blank\" rel=\"noopener noreferrer\">generador de reglas CSP<\/a>:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-19014\" title=\"Generate CSP\" src=\"https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_13_56_16-Generate_your_CSP_ikmjuk.jpg\" alt=\"Generate CSP\" width=\"960\" height=\"1140\" \/><\/p>\n<p>Os recomiendo empezar poniendo para los puntos 1, 2, 3, 4 y 5 &#8216;self&#8217;, para que os quede algo como esto:<\/p>\n<p><code>Content-Security-Policy-Report-Only:: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; report-to reportsuri;<\/code><\/p>\n<p>Cuando visit\u00e9is vuestra p\u00e1gina, ver\u00e9is que todo va bien, pero viendo los informes de Report URI, ver\u00e9is que bloquea ciertas cosas. No ten\u00e9is m\u00e1s que ir a\u00f1adi\u00e9ndolo al generador, como por ejemplo:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-19015\" title=\"CSP Generator\" src=\"https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_14_02_07-Generate_your_CSP_ekaxpz-500x312.jpg\" alt=\"CSP Generator\" width=\"960\" height=\"599\" srcset=\"https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_14_02_07-Generate_your_CSP_ekaxpz-500x312.jpg 500w, https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_14_02_07-Generate_your_CSP_ekaxpz-768x479.jpg 768w, https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_14_02_07-Generate_your_CSP_ekaxpz-570x356.jpg 570w, https:\/\/diego.dehaller.ch\/blog\/wp-content\/uploads\/2020\/05\/2017-01-03_14_02_07-Generate_your_CSP_ekaxpz.jpg 960w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" \/><\/p>\n<p>Y as\u00ed hasta que vuestro log est\u00e9 vac\u00edo. Cuando sea el caso, no ten\u00e9is m\u00e1s que activar las reglas, quitando el modo report-only, y os quedar\u00e1 una cosa tal como os puse antes.<\/p>\n<p>Y muchos os preguntar\u00e9is: \u00bfd\u00f3nde tengo que poner este chorizo que he generado? Pues depende del servidor que teng\u00e1is. Yo lo he hecho para un servidor Apache, pero para otros como IIS o Ngynx tambi\u00e9n existe. En Apache, todo est\u00e1 en el fichero httpd.conf, donde pondr\u00e9is esto:<\/p>\n<p><code>Header set <\/code><\/p>\n<p>y detr\u00e1s el chorizo:<\/p>\n<p><code>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;\"<\/code><\/p>\n<p>Reinici\u00e1is Apache, y a probar. Tendr\u00e9is que tener mucha paciencia, probar con varios navegadores &#8211; s\u00ed amigos, s\u00ed, aqu\u00ed tenemos el mismo problema que con el c\u00f3digo HTML, que depende del navegador veremos una cosa u otra &#8211; y, si no ten\u00e9is dispositivos de varias marcas\/modelos, pedir ayuda &#8211; como hice yo con <a href=\"https:\/\/twitter.com\/julencin2000\" target=\"_blank\" rel=\"noopener noreferrer\">Julen<\/a> (gracias de nuevo).<\/p>\n<p>Como dec\u00eda al principio, todo es esto har\u00e1 que sea m\u00e1s dif\u00edcil que un pirata pueda aprovecharse de vuestro blog para meter su propio c\u00f3digo. Una cosa que tendr\u00e9is que tener en cuenta es que si consigue un acceso completo al servidor, podr\u00e1 quitar las reglas CSP en menos de 30 segundos. O si consigue modificar c\u00f3digo del blog, tampoco valdr\u00e1 de mucho. Pero como digo, complica las cosas un poco m\u00e1s.<\/p>\n<p>\u00a1Saludos!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Hoy en d\u00eda la seguridad mientras navegamos es no ya importante, es crucial. Cada vez recibimos m\u00e1s mensajes con phishing donde servicios de renombre como Paypal, WordPress, Yahoo y otros nos piden que confirmemos nuestros. N\u00f3tese que pongo piden en cursiva, puesto que realmente no son ellos, pero los malos que intentan enga\u00f1arnos. Generalmente [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[2021,2018,2017,2019,2020,535],"class_list":{"0":"post-19007","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-blog","7":"tag-apache","8":"tag-content-security-policy","9":"tag-csp","10":"tag-report-uri","11":"tag-security-headers","12":"tag-seguridad","13":"czr-hentry"},"_links":{"self":[{"href":"https:\/\/diego.dehaller.ch\/blog\/wp-json\/wp\/v2\/posts\/19007","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/diego.dehaller.ch\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/diego.dehaller.ch\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/diego.dehaller.ch\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/diego.dehaller.ch\/blog\/wp-json\/wp\/v2\/comments?post=19007"}],"version-history":[{"count":13,"href":"https:\/\/diego.dehaller.ch\/blog\/wp-json\/wp\/v2\/posts\/19007\/revisions"}],"predecessor-version":[{"id":19500,"href":"https:\/\/diego.dehaller.ch\/blog\/wp-json\/wp\/v2\/posts\/19007\/revisions\/19500"}],"wp:attachment":[{"href":"https:\/\/diego.dehaller.ch\/blog\/wp-json\/wp\/v2\/media?parent=19007"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diego.dehaller.ch\/blog\/wp-json\/wp\/v2\/categories?post=19007"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diego.dehaller.ch\/blog\/wp-json\/wp\/v2\/tags?post=19007"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}