Per creare un'esperienza completa sul web odierno, è quasi inevitabile che incorporare componenti e contenuti sui quali non hai alcun reale controllo. I widget di terze parti possono favorire il coinvolgimento e svolgere un ruolo fondamentale nel contesto complessivo esperienza utente e i contenuti generati dagli utenti a volte sono ancora più importanti rispetto ai contenuti nativi di un sito. L'astensione da una delle due non è un'opzione, ma entrambi aumentano il rischio che si verifichi qualcosa di bruttaTM sul vostro sito. Ciascuna widget che incorpori (ogni annuncio, ogni widget di social media) è un potenziale vettore d’attacco per utenti malintenzionati:
Criterio di sicurezza del contenuto (CSP) possono mitigare i rischi associati a entrambi questi tipi di contenuti offrendo è possibile autorizzare fonti di script specifiche affidabili e altre contenuti. Si tratta di un grande passo nella giusta direzione, ma vale la pena notare che la protezione offerta dalla maggior parte delle direttive CSP è binaria, ovvero consentito o non lo è. Ci sono momenti in cui sarebbe utile dire "Non sicuro che mi fido di questa fonte di contenuti, ma è troppo bello. Incorpora per favore, Browser, ma non lasciare che il mio sito venga danneggiato".
Privilegio minimo
In sostanza, stiamo cercando un meccanismo che ci permetta di concedere ai contenuti Deve incorporare solo il livello minimo di capacità necessario a svolgere il proprio lavoro. Se un widget non deve aprire una nuova finestra popup, rimuovendo così l'accesso a window.open ferito. Se non richiede Flash, la disattivazione del supporto dei plug-in non dovrebbe essere problema. Siamo più sicuri possibile se seguiamo il principio di almeno privilegio e bloccare ogni singola funzione non direttamente pertinente con quella che vorremmo per l'utilizzo. Il risultato è che non dobbiamo più fidarci ciecamente del fatto che di contenuti incorporati non sfruttano privilegi che non dovrebbe utilizzare. it non avranno accesso a queste funzionalità.
Gli elementi iframe
sono il primo passo verso un buon framework per una soluzione di questo tipo.
Il caricamento di un componente non attendibile in un iframe
fornisce una misura di separazione
tra la tua applicazione e i contenuti che vuoi caricare. I contenuti all'interno di frame
non avrà accesso al DOM della tua pagina o ai dati che hai archiviato localmente, né
essere in grado di disegnare in posizioni arbitrarie sulla pagina; è limitato all'ambito
il contorno del frame. Tuttavia, la separazione non è realmente robusta. La pagina contenuta
continua ad avere una serie di opzioni per comportamenti fastidiosi o dannosi: la riproduzione automatica
video, plug-in e popup sono la punta dell'iceberg.
Attributo sandbox
dell'elemento iframe
ci fornisce esattamente ciò di cui abbiamo bisogno per
restringere i limiti dei contenuti racchiusi in frame. Possiamo
indica al browser di caricare i contenuti di un frame specifico con privilegi limitati
dell'ambiente, consentendo solo il sottoinsieme di capacità necessarie per fare
le attività devono essere svolte.
Accorciare, ma verificare
"Tweet" di Twitter è un ottimo esempio di funzionalità che può essere incorporate in modo sicuro nel tuo sito tramite una sandbox. Twitter ti consente di incorporare tramite un iframe con il seguente codice:
<iframe src="https://platform.twitter.com/widgets/tweet_button.html"
style="border: 0; width:130px; height:20px;"></iframe>
Per capire cosa possiamo bloccare, esaminiamo attentamente le funzionalità richiesto dal pulsante. L'HTML che viene caricato nel frame esegue una parte JavaScript dai server di Twitter e genera una finestra popup popolata da un tweeting quando selezionato. Questa interfaccia richiede l'accesso ai cookie per collegare il tweet all'account corretto e richiede la possibilità per inviare il modulo per i tweet. Questo è praticamente tutto: per il frame non serve caricare plug-in, non è necessario navigare nella finestra di primo livello o in nessuna di altri bit di funzionalità. Poiché non richiede questi privilegi, rimuoviamole con il sandboxing dei contenuti del frame.
La limitazione tramite sandbox funziona sulla base di una lista consentita. Iniziamo rimuovendo tutti
autorizzazioni possibili, quindi riattiva le singole funzionalità aggiungendo
alla configurazione della sandbox. Per il widget Twitter, abbiamo
abbiamo deciso di attivare JavaScript, popup, invio di moduli e l'interfaccia
cookie. Possiamo farlo aggiungendo un attributo sandbox
a iframe
con il
valore seguente:
<iframe sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
src="https://platform.twitter.com/widgets/tweet_button.html"
style="border: 0; width:130px; height:20px;"></iframe>
È tutto. Abbiamo fornito al frame tutte le funzionalità di cui ha bisogno e
browser gli negherà utile l'accesso a qualsiasi privilegio per cui non abbiamo
concederla esplicitamente tramite il valore dell'attributo sandbox
.
Controllo granulare sulle funzionalità
Nell'esempio precedente abbiamo visto alcuni dei possibili flag di sandbox, ora i meccanismi interni dell'attributo in dettaglio.
Dato che un iframe con un attributo sandbox vuoto, il documento nel frame verrà completamente limitato tramite sandbox, sottoponendolo alle seguenti restrizioni:
- JavaScript non verrà eseguito nel documento all'interno di frame. Non solo include JavaScript viene caricato esplicitamente tramite tag di script, ma anche gestori di eventi incorporati e JavaScript: URL. Ciò significa anche che i contenuti dei tag noscript esattamente come se l'utente avesse disattivato lo script.
- Il documento all'interno di una cornice viene caricato in un'origine unica, il che significa che tutti i controlli della stessa origine non andranno a buon fine; uniche origini non corrispondono mai ad altre, persino loro stessi. Tra gli altri effetti, ciò significa che il documento non ha Accesso ai dati memorizzati nei cookie di qualsiasi origine o in qualsiasi altro meccanismo di archiviazione (archiviazione DOM, database indicizzato ecc.).
- Il documento all'interno di una cornice non può creare nuove finestre o finestre di dialogo (tramite
window.open
otarget="_blank"
, ad esempio). - Impossibile inviare moduli.
- I plug-in non verranno caricati.
- Il documento all'interno di una cornice può essere visualizzato solo e non in quello principale di primo livello.
L'impostazione di
window.top.location
genererà un'eccezione e facendo clic sul link contarget="_top"
non produrrà alcun effetto. - Funzionalità che si attivano automaticamente (elementi del modulo incentrati automaticamente, riproduzione automatica video ecc.) sono bloccati.
- Impossibile ottenere il blocco del puntatore.
- L'attributo
seamless
viene ignorato nei contenutiiframes
contenuti nel documento all'interno di frame.
È un po' draconiana e un documento è stato caricato in un iframe
completamente sandbox
comporta davvero pochi rischi. Ovviamente, non può essere molto utile:
potrebbe riuscire a utilizzare una sandbox completa per alcuni contenuti statici, ma la maggior parte
delle volte è consigliabile allentare le cose.
Ad eccezione dei plug-in, ognuna di queste restrizioni può essere rimossa aggiungendo un flag al valore dell'attributo sandbox. I documenti con sandbox non possono mai eseguire plug-in, poiché i plug-in sono codice nativo senza sandbox, ma tutto il resto è giusto gioco:
allow-forms
consente l'invio di moduli.allow-popups
consente i popup (sconto!)allow-pointer-lock
consente (una sorpresa!) il blocco del puntatore.allow-same-origin
consente al documento di mantenere la sua origine. pagine caricate dahttps://example.com/
manterrà l'accesso ai dati di quell'origine.allow-scripts
consente l'esecuzione di JavaScript e le funzionalità di si attivano automaticamente (perché sarebbe semplice implementarlo tramite JavaScript).allow-top-navigation
consente al documento di uscire dall'inquadratura del durante la navigazione nella finestra di primo livello.
Tenendo conto di questi aspetti, possiamo valutare esattamente il motivo per cui siamo arrivati insieme di flag di sandbox nell'esempio di Twitter in alto:
allow-scripts
è obbligatorio, perché la pagina caricata nel frame esegue alcune JavaScript per gestire l'interazione dell'utente.allow-popups
è obbligatorio, perché il pulsante fa apparire un modulo di tweeting in una nuova finestra.- Il campo
allow-forms
è obbligatorio, perché il modulo per i tweeting deve essere inviato. - La proprietà
allow-same-origin
è necessaria, come altrimenti i cookie di twitter.com essere inaccessibile e l'utente non è riuscito ad accedere per pubblicare il modulo.
Una cosa importante da notare è che i flag della sandbox applicati a un frame
vengono applicate a tutte le finestre o i frame creati nella sandbox. Ciò significa che abbiamo
per aggiungere allow-forms
alla sandbox del frame, anche se il modulo esiste solo
nella finestra che compare.
Con l'attributo sandbox
attivo, il widget riceve solo le autorizzazioni che
e funzionalità come plug-in, navigazione principale e blocco del puntatore rimangono
bloccato. Abbiamo ridotto il rischio di incorporare il widget, senza effetti negativi.
È un vantaggio per tutti.
Separazione dei privilegi
Limitazione tramite sandbox dei contenuti di terze parti per eseguire codice non attendibile in un un ambiente con privilegi limitati è ovviamente vantaggioso. Ma che dire codice? Ti fidi di te, vero? Perché preoccuparsi della sandbox?
Ritengo la domanda: se il codice non ha bisogno di plug-in, perché dargli l'accesso ai plug-in? Nella migliore delle ipotesi, è un privilegio che non usi mai, nel peggiore dei casi è un un potenziale vettore per gli aggressori per entrare nella porta. Il codice di ognuno ha bug e praticamente ogni applicazione è vulnerabile allo sfruttamento in un modo o un altro. La limitazione tramite sandbox del proprio codice implica che, anche se un utente malintenzionato riesce la tua applicazione, non avrà accesso completo al l'origine dell'applicazione; Potranno svolgere solo attività che l'applicazione che possono fare. Ancora pessimo, ma non così male.
Puoi ridurre ulteriormente il rischio suddividendo l'applicazione in e la limitazione tramite sandbox di ogni elemento con il minor privilegio possibile. Questa tecnica è molto comune nel codice nativo: Chrome, ad esempio, si rompe in un processo del browser con privilegi elevati che ha accesso al disco rigido locale e può effettuare connessioni di rete, e molti processi di renderer con privilegi limitati eseguire il lavoro pesante di analisi di contenuti non attendibili. I renderer non devono toccare disco, il browser si occupa di fornire tutte le informazioni necessarie eseguire il rendering di una pagina. Anche se un hacker astuto trova un modo per corrompere un renderer, non è arrivato molto lontano, perché il renderer non può fare molto interesse da solo: tutti gli accessi con privilegi elevati devono essere indirizzati tramite il processo del browser. Gli aggressori dovranno trovare diversi punti deboli in diverse parti del sistema fare qualche danno, il che riduce enormemente il rischio che il pegno vada a buon fine.
Sandboxing sicuro di eval()
Con la sandbox e
API postMessage
,
il successo di questo modello è abbastanza semplice
da applicare al web. Pezzi di
la tua applicazione può trovarsi in iframe
con sandbox e il documento principale può
le comunicazioni tra di loro pubblicando messaggi e ascoltando
diverse. Questo tipo di struttura garantisce che gli exploit in qualsiasi
minimizzi i danni possibili. Ha anche il vantaggio di costringerti a
creare punti di integrazione chiari, così sai esattamente dove devi essere
e presta molta attenzione alla convalida di input e output. Vediamo un esempio di giocattolo
solo per capire come potrebbe funzionare.
Evalbox è un'applicazione davvero entusiasmante che prende una stringa e la valuta come JavaScript. Wow, vero? Esattamente cosa che hai aspettato da tutti questi lunghi anni. È un percorso abbastanza pericoloso un'applicazione, ovviamente, poiché consentire l'esecuzione di JavaScript arbitrario significa che qualsiasi e tutti i dati che un'origine ha da offrire sono a portata di mano. Riducono il rischio di Bad ThingsTM si verifica assicurando che il codice venga eseguito all'interno di una sandbox, il che rende tutto un po' più sicuro. Lavoreremo per analizzare il codice partendo dai contenuti del frame:
<!-- frame.html -->
<!DOCTYPE html>
<html>
<head>
<title>Evalbox's Frame</title>
<script>
window.addEventListener('message', function (e) {
var mainWindow = e.source;
var result = '';
try {
result = eval(e.data);
} catch (e) {
result = 'eval() threw an exception.';
}
mainWindow.postMessage(result, event.origin);
});
</script>
</head>
</html>
All'interno dell'inquadratura è presente una minima parte di documento che semplicemente ascolta i messaggi
da quello principale collegandoti all'evento message
dell'oggetto window
.
Ogni volta che il publisher principale esegue postMessage nei contenuti dell'iframe, questo evento
verrà attivato, dandoci accesso alla stringa che il nostro padre vorrebbe
eseguire il deployment.
Nel gestore, prendiamo l'attributo source
dell'evento, che è l'elemento principale
finestra. Lo utilizzeremo per rinviare il risultato del nostro duro lavoro una volta che avremo
fatto. Quindi ci occuperemo del lavoro pesante, passando i dati che ci sono stati forniti
eval()
. Questa chiamata è stata raggruppata in un blocco di prova, poiché operazioni vietate
all'interno di un iframe
con sandbox genererà spesso eccezioni DOM; troveremo
e segnalare un semplice messaggio di errore. Infine, pubblichiamo il risultato
torna alla finestra principale. È una cosa piuttosto semplice.
Anche il genitore è semplice. Creeremo una UI molto piccola con un textarea
per il codice e button
per l'esecuzione, e estrarremo frame.html
tramite
con sandbox iframe
, che consente solo l'esecuzione di script:
<textarea id='code'></textarea>
<button id='safe'>eval() in a sandboxed frame.</button>
<iframe sandbox='allow-scripts'
id='sandboxed'
src='frame.html'></iframe>
Ora collegheremo le cose per l'esecuzione. Innanzitutto, ascolteremo le risposte
iframe
e alert()
ai nostri utenti. Presumibilmente un'applicazione reale
potrebbe fare qualcosa di meno fastidioso:
window.addEventListener('message',
function (e) {
// Sandboxed iframes which lack the 'allow-same-origin'
// header have "null" rather than a valid origin. This means you still
// have to be careful about accepting data via the messaging API you
// create. Check that source, and validate those inputs!
var frame = document.getElementById('sandboxed');
if (e.origin === "null" && e.source === frame.contentWindow)
alert('Result: ' + e.data);
});
Successivamente, collegheremo un gestore di eventi ai clic sulla button
. Quando l'utente
clic, prendiamo i contenuti correnti di textarea
e li passiamo alla
frame per l'esecuzione:
function evaluate() {
var frame = document.getElementById('sandboxed');
var code = document.getElementById('code').value;
// Note that we're sending the message to "*", rather than some specific
// origin. Sandboxed iframes which lack the 'allow-same-origin' header
// don't have an origin which you can target: you'll have to send to any
// origin, which might alow some esoteric attacks. Validate your output!
frame.contentWindow.postMessage(code, '*');
}
document.getElementById('safe').addEventListener('click', evaluate);
Facile, no? Abbiamo creato un'API di valutazione molto semplice e possiamo essere certi che il codice valutato non ha accesso a informazioni sensibili come i cookie o archiviazione DOM. Allo stesso modo, il codice valutato non può caricare plug-in, aprire nuove finestre popup, o qualsiasi altra serie di altre attività fastidiose o dannose.
Puoi fare lo stesso con il tuo codice suddividendo le applicazioni monolitiche in e componenti monofunzionali. Ognuno può essere aggregato in una semplice API di messaggistica, come abbiamo scritto sopra. La finestra principale con privilegi elevati può fungere da controller e supervisore, inviando i messaggi in moduli specifici, il minor numero di privilegi possibile per svolgere il proprio lavoro, ascoltare i risultati e assicurando che ogni modulo contenga solo le informazioni necessarie.
Tieni presente, tuttavia, che devi prestare molta attenzione quando hai a che fare con contenuti racchiusi in frame.
che provengono dalla stessa origine dell'elemento principale. Se una pagina del
https://example.com/
incornicia un'altra pagina sulla stessa origine con una sandbox
che includa entrambi i flag allow-same-origin e allow-scripts
la pagina nel frame può arrivare fino all'elemento principale e rimuovere l'attributo sandbox
completamente.
Gioca nella tua sandbox
La limitazione tramite sandbox è ora disponibile in diversi browser: Firefox 17 e versioni successive,
IE10+ e Chrome al momento della stesura (caniuse, naturalmente, ha una versione
assistenza). Applicazione sandbox
in corso...
a iframes
che includi ti consente di concedere determinati privilegi ai
contenuti visualizzati, solo i privilegi necessari per
che i contenuti funzionino correttamente. Questo ti offre l'opportunità di ridurre il rischio
associati all'inclusione di contenuti di terze parti, oltre a ciò che è
già possibile con Content Security
Norme.
Inoltre, la sandbox è una tecnica molto efficace per ridurre il rischio l’autore dell’attacco sarà in grado di sfruttare le falle nel tuo codice. Separando una un'applicazione monolitica in un set di servizi sandbox, ciascuno responsabile di una piccola parte di funzionalità autonome, gli aggressori saranno costretti a compromettono solo frame specifici ma anche il loro titolare. Si tratta di un un'attività molto più difficile, soprattutto perché il controller può essere notevolmente ridotto nell'ambito di applicazione. Puoi dedicare le tue attività di sicurezza al controllo di quel codice se chiedi aiuto al browser per il resto.
Ciò non vuol dire che la sandbox sia una soluzione completa al problema del la sicurezza su internet. Offre una difesa approfondita e, a meno che tu non abbia il controllo sui tuoi utenti non puoi ancora fare affidamento sul supporto browser per tutti i tuoi utenti (se controlli i tuoi utenti, clienti: un ambiente aziendale, ad esempio... evviva!). Un giorno... ma per ora la sandbox è un altro livello di protezione avanzata per rafforzare le difese, non è una difesa completa su cui di cui ti puoi fidare. I livelli sono comunque eccellenti. Ti consiglio di usarlo uno.
Per approfondire
"Separazione dei privilegi nelle applicazioni HTML5" è un articolo interessante che lavora alla progettazione di un piccolo framework, e la relativa applicazione a tre applicazioni HTML5 esistenti.
La sandbox può essere ancora più flessibile se combinata con altri due nuovi iframe attributi:
srcdoc
, eseamless
. La prima ti consente di completare un frame con contenuti senza l'overhead di una richiesta HTTP e quest'ultima consente allo stile di fluire nei contenuti inquadrati. Al momento entrambi hanno un supporto del browser piuttosto scadente (Chrome e WebKit) notturne). ma sarà una combinazione interessante in futuro. Potresti: ad esempio, commenti nella sandbox su un articolo tramite il seguente codice:<iframe sandbox seamless srcdoc="<p>This is a user's comment! It can't execute script! Hooray for safety!</p>"></iframe>