Chrome 18+: ¿cómo permitir secuencias de comandos en línea con una Política de seguridad de contenido?

Chrome 18 Dev / Canary acaba de ser lanzado, y content_security_policy será necesario en el manifiesto para ciertas extensiones.

Intento que un CSP trabaje para scripts en línea, pero no sé si estoy haciendo algo mal o si se trata de un error de Chrome 18.

manifest.json:

 { "name": "CSP Test", "version": "1.0", "manifest_version": 2, "options_page": "test.html", "content_security_policy": "default-src 'unsafe-inline'" } 

test.html:

   alert("hello");   

En Chrome 18, esta extensión descomprimida no se carga, mostrando un error:

No se pudo cargar la extensión desde '[directorio de extensión]'. Valor no válido para 'content_security_policy'.

Si cambio 'unsafe-inline' a 'self' , la extensión se carga bien, pero alert() no funciona, y la consola de la página de opciones contiene un error:

Se negó a ejecutar el script en línea debido a Content-Security-Policy.

En Chrome 16, el uso de 'unsafe-inline' permite que la extensión cargue bien y alert() funciona. Sin embargo, en Chrome 16, reemplazar 'unsafe-inline' con 'foo' permite cargar la extensión, pero por supuesto no deja que funcione la alert() , así que tal vez Chrome 18 sea más estricto que 16, pero …

¿ default-src 'unsafe-inline' no es válido, o es un error? ¿Qué valor de CSP puedo usar para hacer que la alert() funcione en Chrome 18?


Según la respuesta aceptada a continuación, las secuencias de comandos en línea ya no funcionan en las extensiones de Chrome 18. alert() deberá colocarse en su propio archivo JavaScript.

Para las versiones recientes de Chrome (46+), la respuesta actual ya no es verdadera. unsafe-inline todavía no tiene ningún efecto (en el manifiesto y en las tags de encabezado meta ), pero según la documentación , puede utilizar la técnica que se describe aquí para relajar la restricción.

Uso del hash para elementos

La directiva script-src permite a los desarrolladores incluir en la lista blanca un determinado guión en línea especificando su hash como una fuente de script permitida.

El uso es directo. El servidor calcula el hash del contenido de un bloque de script en particular e incluye la encoding base64 de ese valor en el Content-Security-Policy :

 Content-Security-Policy: default-src 'self'; script-src 'self' https://example.com 'sha256-base64 encoded hash' 

Ejemplo

Considera lo siguiente:

manifest.json :

 { "manifest_version": 2, "name": "csp test", "version": "1.0.0", "minimum_chrome_version": "46", "content_security_policy": "script-src 'self' 'sha256-WOdSzz11/3cpqOdrm89LBL2UPwEU9EhbDtMy2OciEhs='", "background": { "page": "background.html" } } 

background.html :

 < !DOCTYPE html>       

Resultado :
diálogo de alerta desde el script en línea

Investigación exahustiva

También probé poniendo la directiva correspondiente en una meta lugar de en el manifiesto. Si bien el CSP indicado en el mensaje de la consola incluía el contenido de la etiqueta, no ejecutaba la secuencia de comandos en línea (en Chrome 53).

new background.html :

 < !DOCTYPE html>         

Resultado :
mensajes de error de la consola sobre la política de seguridad del contenido

Apéndice: generación de los hashes

Aquí hay dos métodos para generar los hashes:

  1. Python (pasar JS a stdin, canalizarlo a otro lugar):
 import hashlib import base64 import sys def hash(s): hash = hashlib.sha256(s.encode()).digest() encoded = base64.b64encode(hash) return encoded contents = sys.stdin.read() print(hash(contents)) 
  1. En JS, utilizando la biblioteca de cifrado de Stanford Javascript :
 var sjcl = require('sjcl'); // Generate base64-encoded SHA256 for given string. function hash(s) { var hashed = sjcl.hash.sha256.hash(s); return sjcl.codec.base64.fromBits(hashed); } 

Al realizar hash en las secuencias de comandos en línea, asegúrese de incluir todo el contenido de la etiqueta de secuencia de comandos (incluidos todos los espacios en blanco iniciales / finales). Si desea incorporar esto en sus comstackciones, puede usar algo como cheerio para obtener las secciones relevantes. Genéricamente, para cualquier html , puedes hacer:

 var $ = cheerio.load(html); var csp_hashes = $('script') .map((i, el) => hash($(el).text()) .toArray() .map(h => `'sha256-${h}'`) .join(' '); var content_security_policy = `script-src 'self' 'unsafe-eval' ${csp_hashes}; object-src 'self'`; 

Este es el método utilizado en hash-csp , un plugin gulp para generar hashes.

La siguiente respuesta es verdadera para las versiones anteriores de Chrome (<46). Para los más recientes, por favor marque @ Chris-Hunt answer https://stackoverflow.com/a/38554505/422670

Acabo de publicar una respuesta muy similar para la pregunta https://stackoverflow.com/a/11670319/422670

Como se dijo, no hay forma de relajar la política de seguridad en línea en las extensiones v2 . unsafe-inline simplemente no funciona, intencionalmente.

Realmente no hay otra manera que mover todos tus javascript a archivos js y señalarlos con un .

Sin embargo, existe la opción de hacer una evaluación y una nueva función dentro de un iframe de espacio aislado, por ejemplo con las siguientes líneas en el manifiesto:

 "sandbox": { "pages": [ "page1.html", "directory/page2.html" ] }, 

Una página de espacio aislado no tendrá acceso a las API de la aplicación o de la extensión ni al acceso directo a páginas que no estén en la zona de pruebas (se puede comunicar con ellas a través de postMessage ()). Puede restringir aún más los derechos de sandbox con un CSP específico

Ahora hay un ejemplo completo del equipo de Google Chrome en github eval en iframe sobre cómo eludir el problema comunicándose con un iframe de espacio aislado, así como un breve tutorial de análisis

Gracias a Google, hay mucha reescritura de extensiones en la alineación 🙁

EDITAR

Es posible relajar la política de seguridad para scripts REMOTOS. Pero no para las líneas.

La política contra eval() y sus parientes como setTimeout(String) , setInterval(String) y new Function(String) se puede relajar agregando 'unsafe-eval' a su política: "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

Sin embargo, recomendamos encarecidamente no hacer esto. Estas funciones son notorios vectores de ataque XSS.

esto apareció en la documentación del tronco y se trata en el hilo "eval re-allowed"

inline scripts no volverán:

No hay ningún mecanismo para relajar la restricción contra la ejecución de JavaScript en línea. En particular, establecer una política de script que incluya 'unsafe-inline' no tendrá ningún efecto.

El uso de hash para scripts en línea está permitido en Content Security Policy Level 2. Del ejemplo en la especificación:

Content-Security-Policy: script-src ‘sha512-YWIzOWNiNzJjNDRlYzc4MTgwMDhmZDlkOWI0NTAyMjgyY2MyMWJlMWUyNjc1ODJlYWJhNjU5MGU4NmZmNGU3OAo =’

Una alternativa es el nonce , una vez más a partir de los ejemplos:

Content-Security-Policy: script-src ‘self’ ‘nonce- $ RANDOM’;

entonces

   

Esto parece ser compatible con Chrome 40+, pero no estoy seguro de la suerte que podría tener con otros navegadores en este momento.

Afaik, esto es un error.

 "default-src 'self' https://ssl.google-analytics.com" 

funciona, mientras

 "default-src 'self' http://ssl.google-analytics.com" 

no.

En realidad, es una tecnología innovadora . Visite http://code.google.com/p/chromium/issues/detail?id=105796 para obtener más información.

Actualización: http://code.google.com/p/chromium/issues/detail?id=107538 se refiere a este problema.