HTML-beveiliging in Adobe AIR

Adobe AIR 1.0 of hoger

In dit onderwerp wordt de AIR HTML-beveiligingsarchitectuur beschreven en leest u hoe iframes, frames en de sandboxbridge worden gebruikt voor het instellen van op HTML gebaseerde toepassingen en hoe u HTML-inhoud veilig kunt integreren in op SWF gebaseerde toepassingen.

De runtime past regels toe en biedt mechanismen voor het verhelpen van mogelijke beveiligingsproblemen in HTML en JavaScript. Hierbij worden altijd dezelfde regels toegepast, ongeacht of uw toepassing hoofdzakelijk in JavaScript is geschreven of dat u de HTML- en JavaScript-inhoud in een SWF-toepassing laadt. Inhoud in de sandbox van een toepassing en inhoud in de sandbox die niet van een toepassing is, hebben verschillende rechten. Wanneer inhoud in een iframe of frame wordt geladen, biedt de runtime een veilig sandboxbridge -mechanisme, waardoor de inhoud van het frame of iframe veilig kan communiceren met de inhoud van de toepassingsbeveiligingssandbox.

De AIR SDK bevat drie klassen voor het renderen van HTML-inhoud.

De HTMLLoader-klasse verschaft nauwe integratie tussen JavaScript-code en de AIR API's.

De StageWebView-klasse is een HTML-renderingklasse die slechts in zeer beperkte mate integreert met de AIR-hosttoepassing. Door de StageWebView-klasse geladen inhoud wordt nooit in de beveiligingssandbox van de toepassing geplaatst en kan geen gegevens benaderen of functies aanroepen in de AIR-hosttoepassing. Op bureaubladplatformen gebruikt de StageWebView-klasse de geïntegreerde, op Webkit gebaseerde AIR HTML-engine die ook door de HTMLLoader-klasse wordt gebruikt. Op mobiele platformen gebruikt de StageWebView-klasse het door het besturingssysteem verschafte HTML-controlemiddel. Op mobiele platformen gelden voor de StageWebView-klasse dus dezelfde beveiligingsoverwegingen en en -problemen als voor de webbrowser van het systeem.

De TextField-klasse kan tekenreeksen met HTML-tekst weergeven. Er kan geen JavaScript worden uitgevoerd, maar de tekst kan koppelingen en extern geladen afbeeldingen bevatten.

Zie JavaScript-beveiligingsfouten voorkomen voor meer informatie.

Overzicht van het configureren van uw HTML-toepassing

Frames en iframes bieden een handige structuur voor het indelen van HTML-inhoud in AIR. Met frames kunt u zowel gegevens persistent houden als veilig werken met externe inhoud.

Aangezien HTML in AIR zijn normale, op pagina's gebaseerde indeling behoudt, wordt de HTML-omgeving volledig vernieuwd als het bovenste frame van de HTML-inhoud naar een andere pagina 'navigeert'. U kunt frames en iframes gebruiken om gegevenspersistentie in AIR te behouden, ongeveer op dezelfde manier als voor een webtoepassing in een browser. Als u de belangrijkste toepassingsobjecten in het bovenste frame plaatst, persisteren ze tot u het frame naar een nieuwe pagina laat navigeren. Gebruik subframes of -iframes om de overgangsdelen van de toepassing te laden en weer te geven. (Er zijn verschillende manieren om voor gegevenspersistentie te zorgen als aanvulling op of in plaats van frames. Bijvoorbeeld cookies, lokale gedeelde objecten, lokale bestandsopslag, gecodeerde bestandsopslag en lokale databaseopslag.)

Aangezien HTML in AIR ook de normale vage grens tussen uitvoerbare code en gegevens heeft, plaatst AIR inhoud in het bovenste frame van de HTML-omgeving in de toepassingssandbox. Na de gebeurtenis load waarbij de pagina wordt geladen, beperkt AIR alle bewerkingen zoals eval() waarbij een tekenreeks kan worden geconverteerd naar een uitvoerbaar object. Deze beperking wordt altijd toegepast, zelfs als een toepassing geen externe inhoud laadt. Als HTML-inhoud deze beperkte bewerkingen mag uitvoeren, moet u frames of iframes gebruiken om de inhoud in een niet-toepassingssandbox te plaatsen. (Soms moet inhoud in een onderliggend sandboxframe worden uitgevoerd wanneer wordt gewerkt met JavaScript-toepassingsraamwerken die zijn gebaseerd op de functie eval() .) Zie Codebeperkingen voor de inhoud van verschillende sandboxen voor de volledige lijst van JavaScript-beperkingen in de toepassingssandbox.

Aangezien HTML in AIR de mogelijkheid behoudt om externe, mogelijk onveilige inhoud te laden, past AIR een 'beleid van zelfde oorsprong' toe om de voorkomen dat de inhoud van een bepaald domein in contact komt met de inhoud van een ander domein. Als u contact tussen de inhoud van de toepassing en de inhoud van een ander domein wilt toestaan, kunt u een bridge creëren die fungeert als interface tussen een hoofd- en een subframe.

Relatie tussen hoofd- en subsandbox creëren

AIR voegt de kenmerken sandboxRoot en documentRoot toe aan de HTML frame- en iframe-elementen. Met deze kenmerken kunt u de toepassingsinhoud behandelen alsof deze van een ander domein afkomstig is:

Attribuut

Beschrijving

sandboxRoot

De URL waarmee de sandbox en het domein worden bepaald waarin de frame-inhoud wordt geplaatst. Het URL-schema file: , http: of https: moet worden gebruikt.

documentRoot

De URL waarvan de frame-inhoud moet worden geladen. Het URL-schema file: , app: of app-storage: moet worden gebruikt.

In het volgende voorbeeld wordt de inhoud van de sandboxsubdirectory van de toepassing zo geconfigureerd dat deze wordt uitgevoerd in de externe sandbox en het domein www.example.com:

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

Bridge tussen hoofd- en een subframes in verschillende sandboxen of domeinen instellen

AIR voegt de eigenschappen childSandboxBridge en parentSandboxBridge toe aan het window -object van een willekeurig subframe. Met deze eigenschappen kunt u bridges definiëren als interfaces tussen een hoofd- en een subframe. Elke bridge gaat in één richting:

childSandboxBridge - met de eigenschap childSandboxBridge kan het subframe een interface toegankelijk maken voor de inhoud van het hoofdframe. Als u een interface toegankelijk wilt maken, stelt u de eigenschap childSandbox in op een functie of object in het subframe. Vervolgens hebt u toegang tot het object of de functie vanuit de inhoud van het hoofdframe. In het volgende voorbeeld ziet u hoe een script dat in een subframe wordt uitgevoerd, een object dat een functie en een eigenschap bevat, toegankelijk kan maken voor het hoofdframe:

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

Als deze onderliggende inhoud zich bevindt in een iframe waaraan de id "child" is toegewezen, hebt u vanuit de bovenliggende inhoud toegang tot de interface door de eigenschap childSandboxBridge van het frame te lezen:

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

parentSandboxBridge - met de eigenschap parentSandboxBridge kan het bovenliggende frame een interface toegankelijk maken voor de inhoud van het subframe. Als u een interface toegankelijk wilt maken, stelt u de eigenschap parentSandbox van het onderliggende frame in op een functie of object in het bovenliggende frame. Vervolgens hebt u toegang tot het object of de functie vanuit de inhoud van het onderliggende frame. In het volgende voorbeeld ziet u hoe een script dat in het bovenliggende frame wordt uitgevoerd, een object dat de functie Save bevat, toegankelijk kan maken voor een onderliggend frame:

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

Via deze interface kan de inhoud van het onderliggende frame bijvoorbeeld tekst opslaan in een bestand met de naam save.txt. De inhoud heeft echter geen andere toegang tot het bestandssysteem. Normaliter moet de toepassingsinhoud de kleinst mogelijke interface toegankelijk maken voor andere sandboxen. De onderliggende inhoud kan bijvoorbeeld de functie Save als volgt aanroepen:

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

Als onderliggende inhoud een eigenschap van het object parentSandboxBridge probeert in te stellen, genereert de runtime een SecurityError-fout. Als bovenliggende inhoud een eigenschap van het object childSandboxBridge probeert in te stellen, genereert de runtime een SecurityError-fout.

Codebeperkingen voor de inhoud van verschillende sandboxen

Zoals beschreven in de inleiding van dit onderwerp, HTML-beveiliging in Adobe AIR , dwingt de runtime regels af en biedt deze mechanismen voor het overwinnen van mogelijke zwakheden in de beveiliging in HTML en JavaScript. De desbetreffende beperkingen staan in dit onderwerp. Als code deze beperkte API's probeert op te roepen, geeft de runtime de foutmelding weer dat er in de runtime van Adobe AIR een beveiligingsfout betreffende JavaScript-code in de toepassingsbeveiligingssandbox is opgetreden.

Zie JavaScript-beveiligingsfouten voorkomen voor meer informatie.

Beperkingen betreffende het gebruik van de JavaScript-functie eval() en soortgelijke technieken

Voor de HTML-inhoud van de toepassingsbeveiligingssandbox zijn er beperkingen betreffende het gebruik van API's die tekenreeksen dynamisch in programmacode kunnen omzetten nadat de code is geladen (nadat de gebeurtenis onload van het element body is verzonden en de handlerfunctie onload is voltooid). Hierdoor wordt voorkomen dat de toepassing onbedoeld code van niet-toepassingsbronnen (zoals mogelijk onveilige netwerkdomeinen) opneemt (en uitvoert).

Als uw toepassing bijvoorbeeld tekenreeksgegevens van een externe bron gebruikt om naar de eigenschap innerHTML van een DOM-element te schrijven, bevat de tekenreeks mogelijk (JavaScript-) programmacode die onveilige bewerkingen kan uitvoeren. Tijdens het laden van de inhoud is er echter geen risico dat externe tekenreeksen in het DOM-element worden ingevoegd.

Eén beperking betreft het gebruik van de JavaScript-functie eval() . Nadat code in de toepassingssandbox is geladen en de gebeurtenishandler onload is verwerkt, kunt u de functie eval() slechts met bepaalde beperkingen gebruiken. De volgende regels gelden voor het gebruik van de functie eval() nadat code is geladen uit de toepassingsbeveiligingssandbox:

  • Expressies met literalen zijn toegestaan. Bijvoorbeeld:

    eval("null"); 
    eval("3 + .14"); 
    eval("'foo'");
  • Objectliteralen zijn toegestaan, zoals in de volgende situatie:

    { prop1: val1, prop2: val2 }
  • Setter/getters met objectliteralen zijn niet toegestaan , zoals in de volgende situatie:

    { get prop1() { ... }, set prop1(v) { ... } }
  • Arrayliteralen zijn toegestaan, zoals in de volgende situatie:

    [ val1, val2, val3 ]
  • Expressies met het lezen van eigenschappen zijn niet toegestaan , zoals in de volgende situatie:

    a.b.c
  • Het oproepen van functies is niet toegestaan .

  • Functiedefinities zijn niet toegestaan .

  • Het instellen van eigenschappen is niet toegestaan .

  • Functieliteralen zijn niet toegestaan .

Tijdens het laden van de code, vóór de gebeurtenis onload , en tijdens de uitvoering van de gebeurtenishandlerfunctie onload gelden deze beperkingen echter niet voor de inhoud van de toepassingsbeveiligingssandbox.

Bij de volgende code bijvoorbeeld treedt een fout op nadat code is geladen:

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

Dynamisch gegenereerde code, zoals bij het oproepen van de functie eval() , zou een veiligheidsrisico zijn als deze toegang kreeg tot de toepassingssandbox. Een toepassing kan bijvoorbeeld onbedoeld een tekenreeks uitvoeren die is geladen vanaf een netwerkdomein en schadelijke code bevat. De code kan bijvoorbeeld bestanden op de computer van de gebruiker verwijderen of wijzigen. Of de inhoud van een lokaal bestand doorsturen naar een niet-vertrouwd netwerkdomein.

Dynamische code kan op de volgende manieren worden gegenereerd:

  • door het oproepen van de functie eval() ;

  • door eigenschappen van het type innerHTML of DOM-functies te gebruiken om scripttags in te voegen die een script buiten de toepassingsmap laden;

  • door eigenschappen van het type innerHTML of DOM-functies te gebruiken om scripttags in te voegen die inline code bevatten (in plaats van een script te laden via het kenmerk src );

  • door het kenmerk src voor script tags zo in te stellen dat een JavaScript-bestand wordt geladen dat zich buiten de toepassingsmap bevindt;

  • door het URL-schema javascript te gebruiken (zoals in href="javascript:alert('Test')" );

  • door de functie setInterval() of setTimeout() te gebruiken, waarbij de eerste parameter (die de functie asynchroon laat uitvoeren) een (te evalueren) tekenreeks en geen functienaam is (zoals in setTimeout('x = 4', 1000) );

  • door document.write() of document.writeln() op te roepen.

Code in de toepassingsbeveiligingssandbox kan tijdens het laden van inhoud alleen deze methoden gebruiken.

Deze beperkingen blokkeren het gebruik van eval() met JSON-objectliteralen niet . Hierdoor kan de inhoud van uw toepassing met de JSON JavaScript-bibliotheek werken. U kunt echter geen overbelaste JSON-code (met gebeurtenishandlers) gebruiken.

Voor andere Ajax-frameworks en JavaScript-codebibliotheken moet u controleren of de code in het framework of de bibliotheek binnen deze beperkingen betreffende dynamisch gegenereerde code werkt. Als dat niet het geval is, neemt u alle inhoud die gebruikmaakt van het framework of de bibliotheek op in een niet-toepassingsbeveiligingssandbox. Zie Beperkingen voor JavaScript in AIR en Scripting tussen toepassings- en niet-toepassingsinhoud . Adobe houdt een lijst bij van Ajax-frameworks waarvan bekend is dat ze de toepassingsbeveiligingssandbox ondersteunen. Ga hiervoor naar http://www.adobe.com/products/air/develop/ajax/features/ .

In tegenstelling tot de inhoud van de toepassingsbeveiligingssandbox kan JavaScript-inhoud van een niet-toepassingsbeveiligingssandbox wel de functie eval() oproepen om op elk gewenst moment dynamisch gegenereerde code uit te voeren.

Beperkingen betreffende de toegang tot AIR API's (voor niet-toepassingssandboxen)

JavaScript-code in een niet-toepassingssandbox heeft geen toegang tot het object window.runtime , zodat deze code geen AIR API's kan uitvoeren. Als de inhoud van een niet-toepassingsbeveiligingssandbox de volgende code oproept, treedt een TypeError-fout op:

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

Het fouttype is TypeError (niet-gedefinieerde waarde) omdat de inhoud van de niet-toepassingssandbox het object window.runtime niet herkent en het als een niet-gedefinieerde waarde beschouwt.

Als u runtime-functionaliteit toegankelijk wilt maken voor de inhoud van een niet-toepassingssandbox, gebruikt u een scriptbridge. Zie Scripting tussen toepassings- en niet-toepassingsinhoud voor meer informatie.

Beperkingen betreffende het gebruik van XMLHttpRequest-oproepen

HTML-inhoud in de beveiligingssandbox van de toepassing kan niet tegelijkertijd XMLHttpRequest-methoden gebruiken voor het laden van buiten de toepassingssandbox terwijl de HTML-inhoud wordt geladen en tijdens de onLoad -gebeurtenis.

De HTML-inhoud van niet-toepassingsbeveiligingssandboxen kan standaard geen JavaScript XMLHttpRequest-object gebruiken om gegevens te laden van andere domeinen dan het domein waarvan de aanvraag afkomstig is. Een tag van het type frame of iframe kan een kenmerk van het type allowcrosscomainxhr bevatten. Als u dit kenmerk instelt op een waarde die niet leeg is, kan de inhoud van het frame of iframe het Javascript XMLHttpRequest-object gebruiken om gegevens te laden uit andere domeinen dan het domein van de code waarvan de aanvraag afkomstig is:

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

Zie Scripting tussen de inhoud van verschillende domeinen voor meer informatie.

Beperkingen betreffende het laden van CSS-, frame-, iframe- en img-elementen (voor de inhoud van niet-toepassingssandboxen)

De HTML-inhoud van externe (netwerk-) beveiligingssandboxen kan alleen inhoud van het type CSS, frame , iframe of img uit externe sandboxen (netwerk-URL's) laden.

De HTML-inhoud van lokaal-met-bestandssysteem, lokaal-met-netwerk of lokaal-vertrouwde sandboxen kan alleen inhoud van het type CSS, frame, iframe of img uit lokale sandboxen (niet van toepassings- of externe sandboxen) laden.

Beperkingen betreffende het oproepen van de JavaScript-methode window.open()

Als een venster dat door het oproepen van de JavaScript-methode window.open() is gemaakt, de inhoud van een niet-toepassingsbeveiligingssandbox weergeeft, begint de titel van het venster met de titel van het hoofdvenster (vanwaaruit het nieuwe venster is geopend), gevolgd door een dubbele punt. U kunt geen code gebruiken om dat deel van de venstertitel buiten het scherm te verplaatsen.

De inhoud van niet-toepassingsbeveiligingssandboxen kan de JavaScript-methode window.open() alleen oproepen als reactie op een gebeurtenis die is gestart door een klik met de muisknop of een druk op een toets van het toetsenbord. Hierdoor wordt voorkomen dat niet-toepassingsinhoud vensters creëert die voor bedrog kunnen worden gebruikt (bijvoorbeeld voor phishingaanvallen). Ook kan de gebeurtenishandler voor de muis- of toetsenbordgebeurtenis de methode window.open() niet zo instellen dat deze na een vertraging wordt uitgevoerd (bijvoorbeeld door de functie setTimeout() op te roepen).

De inhoud van externe (netwerk-) sandboxen kan de methode window.open() alleen gebruiken om de inhoud van externe netwerksandboxen te openen. Deze inhoud kan de methode window.open() niet gebruiken om de inhoud van de toepassingssandbox of van lokale sandboxen te openen.

Inhoud in de sandbox Lokaal-met-bestandssysteem, de sandbox Lokaal-met-netwerk en de sandbox Lokaal-vertrouwd (zie Beveiligingssandboxen ) kan de methode window.open() alleen gebruiken om de inhoud van lokale sandboxen te openen. Deze inhoud kan window.open() niet gebruiken om de inhoud van de toepassingssandbox of van externe sandboxen te openen.

Fouten bij het oproepen van beperkte code

Als u code oproept die niet in een sandbox kan worden gebruikt vanwege deze beveiligingsbeperkingen, geeft de runtime de foutmelding weer dat er in de runtime van Adobe AIR een beveiligingsfout betreffende JavaScript-code in de toepassingsbeveiligingssandbox is opgetreden.

Zie JavaScript-beveiligingsfouten voorkomen voor meer informatie.

Sandboxbescherming bij het laden van HTML-inhoud uit een tekenreeks

Met de methode loadString() van de klasse HTMLLoader kunt u HTML-inhoud bij de uitvoering maken. De gegevens die u gebruikt als HTML-inhoud kunnen echter beschadigd zijn als de gegevens worden geladen uit een onbeveiligde internetbron. Om deze reden wordt HTML die is gemaakt met behulp van de methode loadString() , niet in de toepassingssandbox geplaatst en heeft deze HTML geen toegang tot API's van AIR. U kunt echter wel de eigenschap placeLoadStringContentInApplicationSandbox van een HTMLLoader-object instellen op true, zodat HTML die is gemaakt met de methode loadString() , in de toepassingssandbox wordt geplaatst. Zie HTML-inhoud laden vanuit een tekenreeks voor meer informatie.