2012-08-31 19 views
27

Ho bisogno di servire script inviati dall'utente sul mio sito (un po 'come jsfiddle). Voglio che gli script vengano eseguiti sui browser dei visitatori in modo sicuro, isolati dalla pagina in cui sono pubblicati. Poiché il codice viene inviato dagli utenti, non vi è alcuna garanzia che sia affidabile.Come posso sandbox il contenuto JavaScript inviato dall'utente non affidabile?

In questo momento mi viene in mente tre opzioni:

  • Servire il contenuti inviati dagli utenti in un iframe da un dominio diverso, e si basano sulla politica stessa origine. Ciò richiederebbe la creazione di un dominio aggiuntivo che vorrei evitare, se possibile. Credo che sia così che jsfiddle lo fa. Lo script può ancora fare alcuni danni, cambiando ad esempio top.location.href, che non è l'ideale. http://jsfiddle.net/PzkUw/
  • Utilizzare sandbox attribute. Sospetto che questo non sia ben supportato tra i browser.
  • Sanitizzare gli script prima di servirli. Preferirei non andarci.

Esistono altre soluzioni o raccomandazioni in merito?

Aggiornamento

Se, come sospetto, la prima opzione è la soluzione migliore, cosa può uno script dannoso fare altro che cambiare la posizione superiore della finestra, e come posso evitare questo? Posso manipolare o rifiutare determinati script basati sull'analisi del codice statico, ma questo è hard dato il numero di modi in cui è possibile accedere agli oggetti e la difficoltà analizzando javascript in modo statico in generale. Per lo meno, richiederebbe un parser completo e una serie di regole complesse (alcune, ma sospetto non tutte, delle quali sono presenti in JSLint).

+2

Penso che l'idea del sottodominio sia la migliore. Ho esaminato personalmente questa domanda e non sono riuscito a trovare una soluzione migliore. Una volta ho giocato con il caricamento degli script in modo dinamico tramite XmlHttpRequest e l'esecuzione di eval - non mi ricordo perché l'ho lasciato cadere, però. –

+0

Correlati: http://stackoverflow.com/questions/958997/frame-buster-buster-buster-code-needed- – Petah

+0

Sono d'accordo con @JeremyJStarcher. Indipendentemente da ciò, hai la possibilità di controllare determinati elementi di JS, ** window ** è il più importante? In tal caso, proverei a respingere alcune richieste fatte dall'iframe, ma non sono sicuro di quanto sarebbe facile. – inhan

risposta

4

Alcune idee sugli strumenti che potrebbero essere utili nella tua applicazione: attaccano il problema da due direzioni diverse: Caja compila il codice JavaScript non attendibile in qualcosa che è sicuro mentre AdSafe definisce un sottoinsieme di JavaScript che è sicuro da usare.

Caja

Caja

La Caja compilatore è uno strumento per rendere HTML di terze parti, CSS e JavaScript sicuro per incorporare nel tuo sito web. Consente una ricca interazione tra la pagina di incorporamento e le applicazioni incorporate. Caja utilizza un modello di sicurezza basato su oggetti per consentire una vasta gamma di politiche di sicurezza flessibili, in modo che il tuo sito web possa controllare efficacemente ciò che il codice di terze parti incorporato può fare con i dati dell'utente.

AdSafe

AdSafe

AdSafe lo rende sicuro per mettere il codice ospite (come terza parte sceneggiato pubblicitario o widget) su una pagina web. ADsafe definisce un sottoinsieme di JavaScript abbastanza potente da consentire al codice guest di eseguire interazioni di valore, evitando allo stesso tempo danni o intrusioni dannosi o accidentali. Il sottoinsieme ADsafe può essere verificato meccanicamente da strumenti come JSLint in modo che non sia necessario alcun controllo umano per verificare la sicurezza del codice ospite.Il sottoinsieme ADsafe implementa anche buone pratiche di codifica, aumentando la probabilità che il codice guest venga eseguito correttamente.

+0

Ho esaminato AdSafe. È progettato per script che non sono in frame e pertanto è molto restrittivo. Ad esempio, non puoi fare 'a [i] = 1'. Penso che le restrizioni possano spaventare la maggior parte degli utenti legittimi. Daremo un'occhiata a Caja. – Flash

+0

Puoi comunque fare 'a [+ i] = 1'.(Questo perché quando qualcuno scrive 'a = window; i = 'ev' + 'al'' quindi' a [i] 'significherebbe' eval' e sarebbe impossibile eliminare staticamente tale possibilità.) Ma hai ragione che potrebbe essere troppo restrittivo per le tue esigenze. – rsp

26

Creare un'interfaccia di messaggio ben definita e utilizzare JavaScript Web Worker per il codice che si desidera sandbox. HTML5 Web Workers

I Web worker non hanno accesso ai seguenti oggetti DOM.

  • La finestra oggetto

  • Il documento oggetto oggetto

  • Il genitore

modo che non possono reindirizzare la vostra pagina o modificare i dati su di esso.

È possibile creare un modello e un'interfaccia di messaggistica ben definita in modo che gli utenti possano creare script per Web worker, ma lo script dovrebbe avere l'ultima parola su ciò che viene manipolato.

EDIT Commento di Jordan Gray che collega una libreria JavaScript che sembra fare ciò che ho descritto sopra. https://github.com/eligrey/jsandbox

+0

Sembra una buona alternativa ma potrebbe essere troppo restrittiva. Tuttavia +1 per l'idea. – Christoph

+1

Buon suggerimento. La mia preoccupazione è che i browser più vecchi non supportano questo. Inoltre, i web worker non possono effettuare richieste AJAX (ovvero avrei ancora bisogno di servire da un dominio diverso)? – Flash

+0

@Andrew - In quale scenario vedi un web worker che ha a che fare con le funzionalità AJAX? Se sei preoccupato per lo script di lavoro che impersona l'utente sul tuo dominio, puoi semplicemente utilizzare sessioni senza cookie ed evitare questo problema. Per quanto riguarda la compatibilità del browser, sì, IE9 e versioni precedenti non supportano HTML5. –

-4

Se si vuole sandbox qualche pezzo di codice, eliminando sia l'accesso a dire la finestra , documento e genitore elemento che si potrebbe raggiungere l'avvolgendolo in una chiusura in cui queste sono variabili vuote locali:

(function(window, document, parent /* Whatever you want to remove */){ 
    console.log(this);  // Empty object 
    console.log(window); // undefined 
    console.log(document); // undefined 
    console.log(parent); // undefined 
}).call({}); 

Chiamata con un oggetto vuoto è importante perché altrimenti questo punterà alla finestra oggetto

+7

'console.log (function() {return this;}());': P – Flash

2

Come accennato, l'attributo sandbox dello iframe è già supportato dai principali browser, ma vorrei anche suggerire una soluzione mista: per avviare un web worker all'interno dell'iframe in modalità sandbox. Ciò darebbe un thread separato e proteggerà l'evento dal DOM dell'AVErame in modalità sandbox dal codice non attendibile. Ecco come funziona la mia libreria Jailed. Inoltre, è possibile aggirare qualsiasi restrizione esportando qualsiasi serie di funzioni nella sandbox.

+0

Domanda sulla tua libreria, perché esegui il codice in un iframe sandboxed E un web worker? Non sarebbe abbastanza sicuro avere un iframe normale e quindi eseguire il codice non affidabile in un web worker? Il web worker non ha potuto accedere alla dom dell'iframe, o farlo fare davvero qualcos'altro, eccetto per ciò che si fa nei callback di onmessage. Ho ragione? – lastmjs

+2

Beh, non esattamente. Inizialmente eseguiva il codice solo in un web worker, poi mi è stato spiegato che non è sufficiente, dal momento che un lavoratore ha ancora accesso ad alcune istanze di origine locali, come storage locale, indexeddb, ecc. Quindi ho dovuto mettere un lavoratore in una iframe sandboxed. Un lavoratore era comunque utile per ottenere un thread e impedire il blocco della pagina con un ciclo infinito. Ma in seguito è emerso che molti browser vietano l'esecuzione di worker in un iframe sotto https, quindi ora la libreria avvia un worker solo se possibile, altrimenti il ​​codice viene semplicemente eseguito in un iframe. – asvd

Problemi correlati