Chrome 18+: come consentire la creazione di script in linea con una politica di sicurezza dei contenuti?

Chrome 18 Dev / Canary è appena stato rilasciato e content_security_policy sarà necessario nel manifest per determinate estensioni.

Sto cercando di far funzionare un CSP per lo scripting in linea, ma non so se sto facendo qualcosa di sbagliato o se si tratta di un bug di 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");   

In Chrome 18, questa estensione decompressa non riesce a caricare, visualizzando un errore:

Se cambio 'unsafe-inline' in 'self' , l’estensione viene caricata correttamente, ma alert() non funziona e la console della pagina delle opzioni contiene un errore:

Rifiutato di eseguire script inline a causa di Content-Security-Policy.

In Chrome 16, l’uso di 'unsafe-inline' rende l’estensione carica e anche l’ alert() funziona. Tuttavia, in Chrome 16, la sostituzione di 'unsafe-inline' con 'foo' consente il caricamento dell’estensione, ma ovviamente non consente a alert() funzionare, quindi forse Chrome 18 è più rigido di 16, ma …

default-src 'unsafe-inline' non è effettivamente valido, o si tratta di un bug? Quale valore CSP posso utilizzare per rendere alert() funzionante in Chrome 18?


In base alla risposta accettata di seguito, gli script inline non funzionano più nelle estensioni in Chrome 18. alert() dovrà essere inserito nel proprio file JavaScript.

Per le versioni recenti di Chrome (46+) la risposta corrente non è più valida. unsafe-inline non ha ancora alcun effetto (nei tag manifest e in meta header), ma per la documentazione , è ansible utilizzare la tecnica qui descritta per ridurre la restrizione.

Uso hash per gli elementi

La direttiva script-src consente agli sviluppatori di autorizzare un particolare script inline specificandone l'hash come origine consentita di script.

L'utilizzo è semplice. Il server calcola l'hash di un particolare contenuto del blocco di script e include la codifica base64 di quel valore nell'intestazione Content-Security-Policy :

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

Esempio

Considera quanto segue:

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 :

        

Risultato :
finestra di avviso da script in linea

Ulteriori indagini

Ho anche provato a mettere la direttiva applicabile in un meta tag al posto del manifest. Mentre il CSP indicato nel messaggio della console includeva il contenuto del tag, non avrebbe eseguito lo script inline (in Chrome 53).

nuovo background.html :

          

Risultato :
messaggi di errore della console sulla politica di sicurezza del contenuto

Appendice: generazione degli hash

Ecco due metodi per generare gli hash:

  1. Python (passare JS allo stdin, collegarlo da qualche altra parte):
 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. In JS, utilizzando la libreria di crittografia Javascript Stanford :
 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); } 

Assicurati quando esegui l'hash degli script inline che l' intero contenuto del tag script è incluso (inclusi tutti gli spazi bianchi iniziali / finali). Se vuoi incorporare questo nei tuoi build, puoi usare qualcosa come cheerio per ottenere le sezioni pertinenti. Generalmente, per qualsiasi html , puoi fare:

 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'`; 

Questo è il metodo usato in hash-csp , un plugin per gulp per generare hash.

La seguente risposta è vera per le versioni precedenti di Chrome (<46). Per quelli più recenti, controlla @ risposta Chris-Hunt https://stackoverflow.com/a/38554505/422670

Ho appena pubblicato una risposta molto simile per la domanda https://stackoverflow.com/a/11670319/422670

Come detto, non c’è modo di attenuare la politica di sicurezza inline nelle estensioni v2 . unsafe-inline non unsafe-inline semplicemente non funziona, intenzionalmente.

Non c’è davvero altro modo di spostare tutti i javascript in file js e puntarli con uno .

C'è, tuttavia, l'opzione per fare Eval e la nuova funzione all'interno di un iframe sandbox, ad esempio con le seguenti righe nel manifest:

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

Una pagina in modalità sandbox non avrà accesso alle API di estensione o delle app o all'accesso diretto alle pagine non in modalità sandbox (potrebbe comunicare con loro tramite postMessage ()). È ansible limitare ulteriormente i diritti sandbox con un CSP specifico

Esiste ora un esempio completo del team di Google Chrome su github eval in iframe su come aggirare il problema comunicando con un iframe sandboxed, nonché un breve tutorial di analisi

Grazie a Google, c'è un sacco di riscrittura delle estensioni in lineup 🙁

MODIFICARE

È ansible attenuare la politica di sicurezza per gli script REMOTE. Ma non per inline.

La politica contro eval() e i suoi parenti come setTimeout(String) , setInterval(String) e new Function(String) può essere rilassata aggiungendo 'unsafe-eval' alla tua policy: "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

Tuttavia, raccomandiamo vivamente di non farlo. Queste funzioni sono noti vettori di attacco XSS.

questo è apparso nella documentazione del tronco ed è discusso nel thread "eval re-allowed"

Tuttavia, gli inline scripts non torneranno:

Non esiste alcun meccanismo per rilassare la limitazione contro l'esecuzione di JavaScript in linea. In particolare, l'impostazione di una politica di script che include 'unsafe-inline' avrà alcun effetto.

L’utilizzo di hash per gli script inline è consentito in Content Security Policy Level 2. Dall’esempio nelle specifiche:

Politica di sicurezza dei contenuti: script-src ‘sha512-YWIzOWNiNzJjNDRlYzc4MTgwMDhmZDlkOWI0NTAyMjgyY2MyMWJlMWUyNjc1ODJlYWJhNjU5MGU4NmZmNGU3OAo =’

Un’alternativa è il nonce , sempre dagli esempi:

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

poi

   

Questi file sono supportati in Chrome 40+, ma non sono sicuro della fortuna che si avrebbe con altri browser al momento.

Afaik, questo è un bug.

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

funziona, mentre

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

doesnt.

È una tecnologia davvero all’avanguardia, controlla http://code.google.com/p/chromium/issues/detail?id=105796 per i dettagli.

Aggiornamento: http://code.google.com/p/chromium/issues/detail?id=107538 fa riferimento a questo problema.