Sicurezza HTML in Adobe AIR

Adobe AIR 1.0 e versioni successive

In questo argomento viene descritta l'architettura di sicurezza del contenuto HTML in AIR e come utilizzare gli iframe, i frame e il bridge sandbox per configurare applicazioni basate su HTML, nonché integrare contenuto HTML in applicazioni basate su SWF.

Il runtime applica le regole a fornisce i meccanismi per superare le eventuali vulnerabilità di sicurezza in HTML e JavaScript. Vengono applicate le stesse regole, sia che la vostra applicazione sia scritta principalmente in JavaScript o se caricate il contenuto HTML e JavaScript in un'applicazione basata su SWF. Il contenuto nella sandbox dell'applicazione e quello nella sandbox di sicurezza non dell'applicazione hanno privilegi diversi. Quando carica del contenuto in un iframe o in un frame, il runtime fornisce un meccanismo di bridge sandbox protetto che consente al contenuto del frame o dell'iframe di comunicare in modo sicuro con il contenuto presente nella sandbox di sicurezza dell'applicazione.

AIR SDK fornisce tre classi per il rendering del contenuto HTML.

La classe HTMLLoader consente integrazione stretta tra il codice JavaScript e le API di AIR.

La classe StageWebView è una classe di rendering HTML e dispone di scarsa integrazione con l'applicazione AIR host. Il contenuto caricato dalla classe StageWebView non viene mai inserito nella sandbox di sicurezza dell'applicazione e non può accedere a dati o chiamare funzioni nell'applicazione AIR host. Su piattaforme desktop, la classe StageWebView utilizza il motore HTML AIR, basato su Webkit, che è anche utilizzato dalla classe HTMLLoader. Su piattaforme mobili, la classe StageWebView utilizza il controllo HTML fornito dal sistema operativo. Pertanto, su piattaforme mobili la classe StageWebView ha le stesse considerazioni e vulnerabilità di sicurezza del browser Web di sistema.

La classe TextField può visualizzare stringhe di testo HTML. Non è possibile eseguire nessun codice JavaScript, ma il testo può includere collegamenti e immagini caricate esternamente.

Per ulteriori informazioni, consultate Errori JavaScript relativi alla sicurezza da evitare .

Panoramica della configurazione di un'applicazione basata su HTML

I frame e gli iframe costituiscono una struttura pratica per organizzare il contenuto HTML in AIR. I frame consentono di mantenere la persistenza dei dati e utilizzare in modo sicuro il contenuto remoto.

Poiché il contenuto HTML in AIR mantiene la propria normale organizzazione basata su pagine, l'ambiente HTML viene completamente aggiornato se il frame superiore del contenuto HTML “passa” a una pagina diversa. Potete usare frame e iframe per mantenere la persistenza dei dati in AIR, così come fareste per un'applicazione Web in esecuzione in un browser. Potete definire gli oggetti principali dell'applicazione nel frame superiore, che rimarranno persistenti finché non consentirete al frame di passare a una nuova pagina. Utilizzate frame o iframe secondari per caricare e visualizzare le parti non persistenti dell'applicazione. (Vi sono molti modi per mantenere la persistenza dei dati che potete usare insieme o al posto dei frame, ad esempio cookie, oggetti condivisi locali, memorizzazione locale dei file e memorizzazione locale del database).

Poiché nel contenuto HTML in AIR viene mantenuta la normale riga sfocata tra il codice eseguibile e i dati, in AIR il contenuto viene inserito nel frame superiore dell'ambiente HTML, nella sandbox dell'applicazione. Dopo l'evento load della pagina, viene limitata qualsiasi operazione, ad esempio eval() , che possa convertire una stringa di testo in un oggetto eseguibile. Questa restrizione viene applicata anche quando un'applicazione non carica contenuto remoto. Per consentire al contenuto HTML di eseguire queste operazioni con restrizioni, dovete utilizzare frame o iframe per inserire contenuto in una sandbox non di applicazione. L'esecuzione di contenuto in un frame secondario inserito in una sandbox può risultare necessario quando usate alcune strutture di applicazioni JavaScript che si basano sulla funzione eval() . Per un elenco completo di restrizioni relative a JavaScript nella sandbox dell'applicazione, consultate Restrizioni relative al codice per il contenuto presente in diverse sandbox .

Poiché il contenuto HTML in AIR mantiene la capacità di caricare contenuto remoto e possibilmente non sicuro, in AIR viene applicato un criterio basato sulla stessa origine, che impedisce al contenuto presente in un dominio di interagire con il contenuto in un altro dominio. Per consentire l'interazione tra il contenuto dell'applicazione e il contenuto in un altro dominio, potete configurare un bridge che funga da interfaccia tra un frame principale e un frame secondario.

Impostazione di una relazione principale-secondaria tra sandbox

In AIR vengono aggiunti gli attributi sandboxRoot e documentRoot agli elementi HTML frame e iframe. Questi attributi consentono di considerare il contenuto dell'applicazione come se provenisse da un altro dominio:

Attributo

Descrizione

sandboxRoot

URL da usare per determinare la sandbox e il dominio in cui inserire il contenuto del frame. È necessario usare gli schemi URL file: , http: o https: .

documentRoot

URL da cui caricare il contenuto del frame. È necessario usare gli schemi URL file: , app: , o app-storage: .

Nell'esempio seguente, il contenuto installato nella sottodirectory della sandbox dell'applicazione viene mappato in modo che sia eseguito nella sandbox remota e nel dominio www.example.com:

<iframe 
    src="ui.html"  
    sandboxRoot="http://www.example.com/local/"  
    documentRoot="app:/sandbox/"> 
</iframe>

Impostazione di un bridge tra frame principali e secondari in sandbox o domini diversi

In AIR vengono aggiunte le proprietà childSandboxBridge e parentSandboxBridge all'oggetto window di qualsiasi frame secondario. Queste proprietà consentono di definire i bridge che fungono da interfaccia tra un frame principale e uno secondario. Ogni bridge è unidirezionale:

childSandboxBridge : la proprietà childSandboxBridge consente al frame secondario di esporre un'interfaccia per il contenuto del frame principale. Per esporre un'interfaccia, impostate la proprietà childSandbox su una funzione o un oggetto nel frame secondario. Potete quindi accedere all'oggetto o alla funzione dal contenuto nel frame principale. Nell'esempio seguente viene illustrato il modo in cui uno script in esecuzione in un frame secondario possa esporre un oggetto contenente una funzione e una proprietà al relativo frame principale:

var interface = {}; 
interface.calculatePrice = function(){ 
    return .45 + 1.20; 
} 
interface.storeID = "abc" 
window.childSandboxBridge = interface;

Se questo primo contenuto secondario si trova in un iframe a cui è assegnato un id "child" , potete accedere all'interfaccia dal contenuto principale mediante la lettura della proprietà childSandboxBridge del frame:

var childInterface = document.getElementById("child").childSandboxBridge; 
air.trace(childInterface.calculatePrice()); //traces "1.65" 
air.trace(childInterface.storeID)); //traces "abc"

parentSandboxBridge : la proprietà parentSandboxBridge consente al frame principale di esporre un'interfaccia per il contenuto del frame secondario. Per esporre un'interfaccia, impostate la proprietà parentSandbox del frame secondario su una funzione o un oggetto nel frame principale. Potete quindi accedere all'oggetto o alla funzione dal contenuto nel frame secondario. Nell'esempio seguente viene illustrato il modo in cui uno script in esecuzione nel frame principale può esporre un oggetto contenente una funzione save a un frame secondario:

var interface = {}; 
interface.save = function(text){ 
    var saveFile = air.File("app-storage:/save.txt"); 
    //write text to file 
} 
document.getElementById("child").parentSandboxBridge = interface;

Usando questa interfaccia, il contenuto nel frame secondario potrebbe salvare del testo in un file di nome save.txt. Tuttavia, non disporrebbe di alcun altro tipo di accesso al file system. In generale, il contenuto dell'applicazione dovrebbe esporre l'interfaccia più limitata possibile alle altre sandbox. Il contenuto secondario può chiamare la funzione save nel seguente modo:

var textToSave = "A string."; 
window.parentSandboxBridge.save(textToSave);

Se il contenuto secondario tenta di impostare una proprietà dell'oggetto parentSandboxBridge , il runtime genera un'eccezione SecurityError. Se il contenuto principale tenta di impostare una proprietà dell'oggetto childSandboxBridge , il runtime genera un'eccezione SecurityError.

Restrizioni relative al codice per il contenuto presente in diverse sandbox

Come illustrato nell'introduzione di questo argomento, Sicurezza HTML in Adobe AIR , il runtime applica le regole a fornisce i meccanismi per superare le eventuali vulnerabilità di sicurezza in HTML e JavaScript. In questo argomento sono elencate tali restrizioni. Se il codice tenta di chiamare queste API con restrizioni, il runtime genera un errore con un messaggio in cui è indicato che si è verificata una violazione della sicurezza del runtime di Adobe AIR per il codice JavaScript nella sandbox di sicurezza dell'applicazione.

Per ulteriori informazioni, consultate Errori JavaScript relativi alla sicurezza da evitare .

Restrizioni all'uso della funzione JavaScript eval()e tecniche simili

Per il contenuto HTML presente nella sandbox di sicurezza dell'applicazione, sono presenti limitazioni all'uso di API che possono trasformare dinamicamente delle stringhe in codice eseguibile dopo il caricamento del codice (dopo l'invio dell'evento onload dell'elemento body e al termine dell'esecuzione della funzione del gestore onload ). Questa limitazione ha lo scopo di impedire che l'applicazione introduca inavvertitamente, ed esegua, codice da origini non dell'applicazione (ad esempio domini di rete potenzialmente non sicuri).

Se, ad esempio, nella vostra applicazione usate dati in formato stringa da un'origine remota per scrivere nella proprietà innerHTML di un elemento DOM, la stringa potrebbe includere codice (JavaScript) eseguibile che può eseguire operazioni non sicure. Durante il caricamento del contenuto, tuttavia, non vi è alcun rischio di inserire stringhe remote nell'elemento DOM.

Una restrizione riguarda l'uso della funzione JavaScript eval() . Una volta caricato il codice nella sandbox dell'applicazione e dopo l'elaborazione del gestore di eventi onload, potete usare la funzione eval() solo in modo limitato. Le seguenti regole si applicano all'uso della funzione eval() dopo il caricamento del codice dalla sandbox di sicurezza dell'applicazione:

  • Le espressioni che comportano valori letterali sono consentite. Ad esempio:

    eval("null"); 
    eval("3 + .14"); 
    eval("'foo'");
  • I valori letterali oggetto sono consentiti, come nel seguente esempio:

    { prop1: val1, prop2: val2 }
  • I setter/getter dei valori letterali oggetto non sono consentiti , come nell'esempio seguente:

    { get prop1() { ... }, set prop1(v) { ... } }
  • I valori letterali di array sono consentiti, come nell'esempio seguente:

    [ val1, val2, val3 ]
  • Le espressioni che comportano letture di proprietà non sono consentite , come nell'esempio seguente:

    a.b.c
  • La chiamata di funzione non è consentita .

  • Le definizioni di funzione non sono consentite .

  • L'impostazione di una qualsiasi proprietà non è consentita .

  • I valori letterali di funzione non sono consentiti .

Tuttavia, durante il caricamento del codice, prima dell'evento onload e durante l'esecuzione della funzione del gestore di eventi onload , queste restrizioni non si applicano al contenuto presente nella sandbox di sicurezza dell'applicazione.

Dopo il caricamento del codice, ad esempio, il codice riportato di seguito causa la generazione di un'eccezione da parte del runtime:

eval("alert(44)"); 
eval("myFunction(44)"); 
eval("NativeApplication.applicationID");

Il codice generato dinamicamente, come quello risultante dalla chiamata alla funzione eval() , rappresenta un rischio per la sicurezza qualora fosse consentito all'interno della sandbox dell'applicazione. Un'applicazione, ad esempio, potrebbe inavvertitamente eseguire una stringa caricata da un dominio di rete e quella stringa potrebbe contenere codice dannoso. Questo codice potrebbe, ad esempio, eliminare o modificare dei file nel computer dell'utente. Potrebbe, in alternativa, trattarsi di codice che riporta il contenuto di un file locale a un dominio di rete non attendibile.

Di seguito sono elencati i metodi per generare codice dinamico:

  • Chiamata alla funzione eval() .

  • Uso delle proprietà innerHTML o di funzioni DOM per inserire tag script che caricano uno script all'esterno della directory dell'applicazione.

  • Uso delle proprietà innerHTML o di funzioni DOM per inserire tag script che caricano uno script all'esterno della directory dell'applicazione.

  • Impostazione dell'attributo src per i tag script per caricare un file JavaScript che si trova all'esterno della directory dell'applicazione.

  • Uso dello schema URL javascript (come in href="javascript:alert('Test')" ).

  • Uso della funzione setInterval() o setTimout() dove il primo parametro (che definisce il funzionamento asincrono della funzione) è una stringa (da valutare) anziché il nome di una funzione (come in setTimeout('x = 4', 1000) ).

  • Chiamata a document.write() o document.writeln() .

Il codice nella sandbox di sicurezza dell'applicazione può chiamare questi metodi solo durante il caricamento del contenuto.

Queste restrizioni non impediscono l'uso di eval() con i valori letterali JSON, in modo il contenuto della vostra applicazione possa interagire con la libreria JavaScript JSON. Tuttavia, non potete utilizzare codice JSON overloaded (con gestori di eventi).

Per altre strutture Ajax e librerie di codice JavaScript, verificate se il codice nella struttura o nella libreria funziona in base a queste restrizioni sul codice generato dinamicamente. In caso contrario, includete il contenuto che utilizza la struttura o la libreria in una sandbox di sicurezza non dell'applicazione. Per informazioni dettagliate, vedete Restrizioni per JavaScript in AIR e Creazione di script tra contenuto dell'applicazione e non dell'applicazione . Adobe rende disponibile un elenco di strutture Ajax che notoriamente supportano la sandbox di sicurezza dell'applicazione all'indirizzo http://www.adobe.com/it/products/air/develop/ajax/features/ .

A differenza del contenuto presente nella sandbox di sicurezza dell'applicazione, al contenuto JavaScript in una sandbox di sicurezza non dell'applicazione è consentito chiamare la funzione eval() per eseguire il codice generato dinamicamente in qualsiasi momento.

Restrizioni relative all'accesso alle API AIR (per sandbox non dell'applicazione)

Il codice JavaScript HTML in una sandbox non dell'applicazione non dispone dell'accesso all'oggetto window.runtime , pertanto questo codice non può eseguire le API AIR. Se il contenuto in una sandbox di sicurezza non dell'applicazione chiama il seguente codice, l'applicazione genera un'eccezione TypeError:

try { 
    window.runtime.flash.system.NativeApplication.nativeApplication.exit(); 
}  
catch (e)  
{ 
    alert(e); 
}

Il tipo di eccezione è TypeError (valore undefined), in quanto il contenuto nella sandbox non dell'applicazione non riconosce l'oggetto window.runtime , quindi viene visto come un valore undefined.

Potete esporre la funzionalità runtime per il contenuto presente in una sandbox non dell'applicazione utilizzando un bridge script. Per maggiori dettagli, consultate Creazione di script tra contenuto dell'applicazione e non dell'applicazione .

Restrizioni all'uso di chiamate a XMLHttpRequest

Al contenuto HTML nella sandbox di sicurezza dell'applicazione non è consentito utilizzare metodi XMLHttpRequest sincroni per caricare dati dall'esterno della sandbox dell'applicazione durante il caricamento del contenuto HTML e durante l'evento onLoad .

Per impostazione predefinita, al contenuto delle sandbox di sicurezza non dell'applicazione non è consentito utilizzare l'oggetto JavaScript XMLHttpRequest per caricare i dati da domini diversi da quello da cui ha origine la chiamata di richiesta. Un tag frame o iframe può includere un attributo allowcrosscomainxhr . L'impostazione di questo attributo su qualsiasi valore non null consente al contenuto presente nel frame o nell'iframe di utilizzare l'oggetto XMLHttpRequest JavaScript per caricare i dati da domini diversi da quello del codice da cui ha origine la chiamata di richiesta:

<iframe id="UI" 
    src="http://example.com/ui.html" 
    sandboxRoot="http://example.com/" 
    allowcrossDomainxhr="true" 
    documentRoot="app:/"> 
</iframe>

Per ulteriori informazioni, consultate Creazione di script tra contenuti in diversi domini .

Restrizioni relative al caricamento di elementi CSS, frame, iframe e img (per il contenuto presente nelle sandbox non dell'applicazione)

Al contenuto HTML nelle sandbox di sicurezza (di rete) remote è consentito caricare solo contenuto CSS, frame , iframe e img da sandbox remote (da URL di rete).

Al contenuto HTML nella sandbox locale con file system, locale con rete o locale affidabile è consentito caricare solo contenuto CSS, frame, iframe e img da sandbox locali (non da sandbox dell'applicazione o remote).

Restrizioni relative alla chiamata al metodo JavaScript window.open()

Se in una finestra creata tramite una chiamata al metodo JavaScript window.open() viene visualizzato il contenuto da una sandbox di sicurezza non dell'applicazione, il titolo della finestra inizia con il titolo della finestra principale (di avvio) seguito da un carattere due punti. Non potete usare il codice per spostare quella parte del titolo della finestra fuori dallo schermo.

Il contenuto presente nelle sandbox di sicurezza non dell'applicazione può chiamare in modo corretto solo il metodo JavaScript window.open() in risposta a un evento attivato da un'interazione dell'utente mediante il mouse o la tastiera. In questo modo viene impedito al contenuto non dell'applicazione di creare finestre che potrebbero essere utilizzate in modo ingannevole, ad esempio per attacchi mediante phishing. Inoltre, il gestore eventi per l'evento del mouse o della tastiera non può impostare il metodo window.open() affinché venga eseguito dopo un determinato ritardo (ad esempio chiamando la funzione setTimeout() ).

Il contenuto presente nelle sandbox (di rete) remote può usare il metodo window.open() solo per aprire il contenuto di sandbox di rete remote. Non può invece usare il metodo window.open() per aprire contenuto da sandbox dell'applicazione o locali.

Il contenuto nelle sandbox locale con file system, locale con o locale affidabile (vedete Sandbox di sicurezza ) può usare il metodo window.open() solo per aprire il contenuto in sandbox locali. Non può invece usare il metodo window.open() per aprire contenuto da sandbox dell'applicazione o remote.

Errori durante la chiamata a codice con restrizioni

Se chiamate un codice che per ragioni di sicurezza ha limitazioni d'uso in una sandbox, il runtime invia l'errore JavaScript “Adobe AIR runtime security violation for JavaScript code in the application security sandbox” (Violazione della sicurezza di Adobe AIR in fase di runtime per il codice JavaScript nella sandbox dell'applicazione).

Per ulteriori informazioni, consultate Errori JavaScript relativi alla sicurezza da evitare .

Protezione con sandbox quando il contenuto HTML viene caricato da una stringa

Il metodo loadString() della classe HTMLLoader consente di creare contenuto HTML in fase di runtime. Se, tuttavia, come contenuto HTML usate dati che vengono caricati da un'origine Internet non sicura, questi potrebbero essere danneggiati. Per questo motivo, per impostazione predefinita, il contenuto HTML creato tramite il metodo loadString() non viene inserito nella sandbox dell'applicazione e non dispone quindi dell'accesso alle API di AIR. Potete, tuttavia, impostare la proprietà placeLoadStringContentInApplicationSandbox di un oggetto HTMLLoader su true per inserire il contenuto HTML creato tramite il metodo loadString() nella sandbox dell'applicazione. Per ulteriori informazioni, consultate Caricamento di contenuto HTML da una stringa .