Cross-Scripting von Inhalten in unterschiedlichen Sicherheits-Sandboxen

Adobe AIR 1.0 und höher

Das Laufzeitsicherheitsmodell isoliert Code unterschiedlicher Herkunft. Durch Cross-Scripting von Inhalt in unterschiedlichen Sicherheits-Sandboxen können Sie Inhalt in einer Sicherheits-Sandbox den Zugriff auf ausgewählte Eigenschaften und Methoden in einer anderen Sandbox gestatten.

AIR-Sicherheits-Sandboxen und JavaScript-Code

AIR setzt Herkunftsrichtlinien durch, die verhindern, dass Code aus einer Domäne mit Inhalt in einer anderen Domäne interagiert. Alle Dateien werden entsprechend ihrer Herkunft in einer Sandbox abgelegt. Normalerweise kann Inhalt in der Anwendungs-Sandbox nicht gegen das Herkunftsprinzip verstoßen und Cross-Script-Inhalt nicht von außerhalb des Installationsverzeichnisses der Anwendung geladen werden. AIR bietet allerdings einige Verfahren zum Cross-Scripting anwendungsfremden Inhalts.

Eines dieser Verfahren ordnet Anwendungsinhalt mit Frames oder Inlineframes einer anderen Sicherheits-Sandbox zu. Einige aus dem Sandbox-Bereich der Anwendung geladenen Seiten verhalten sich so, als seien sie aus der Remotedomäne geladen worden. Beim Zuordnen von Anwendungsinhalt zur Domäne example.com könnte dieser Inhalt beispielsweise zum Cross-Scripting von Seiten führen, die aus example.com geladen wurden.

Da dieses Verfahren den Anwendungsinhalt in einer anderen Sandbox ablegt, unterliegt Code mit diesem Inhalt nicht mehr den Beschränkungen für die Ausführung von Code in bewerteten Strings. Mit diesem Zuordnungsverfahren für Sandboxen können sie die Beschränkungen selbst dann aufheben, wenn das Cross-Scripting von Remoteinhalt nicht nötig ist. Das Zuordnen von Inhalt auf diese Weise kann insbesondere bei der Arbeit mit einer der zahlreichen JavaScript-Architekturen oder mit bestehendem Code von Nutzen sein, für den die Bewertung von Strings erforderlich ist. Sie sollten jedoch das zusätzliche Risiko bedenken, dass beim Ausführen von Inhalt außerhalb der Anwendungs-Sandbox nicht vertrauenswürdiger Inhalt eingeführt und ausgeführt werden könnte, und sich dagegen absichern.

Gleichzeitig verliert einer anderen Sandbox zugeordneter Anwendungsinhalt seinen Zugriff auf die AIR-APIs, sodass mit dem Zuordnungsverfahren für Sandboxen AIR-Funktionen nicht für außerhalb der Anwendungs-Sandbox ausgeführten Code offen gelegt werden können.

Ein weiteres Cross-Scripting-Verfahren ermöglicht Ihnen die Erstellung einer als Sandbox-Brücke bezeichneten Schnittstelle zwischen Inhalt in einer anwendungsfremden Sandbox und dem übergeordneten Dokument in der Anwendungs-Sandbox. Mit dieser Brücke kann der untergeordnete Inhalt auf vom übergeordneten Inhalt definierte Eigenschaften und Methoden und/oder der übergeordnete Inhalt auf vom untergeordneten Inhalt definierte Eigenschaften und Methoden zugreifen.

Und schließlich können Sie domänenübergreifende XMLHttpRequests über die Anwendungs-Sandbox und, wahlweise, über andere Sandboxen durchführen.

Weitere Informationen finden Sie unter HTML-Frame- und iFrame-Elemente , HTML-Sicherheit in Adobe AIR und Das XMLHttpRequest-Objekt .

Laden von Anwendungsinhalten in eine anwendungsfremde Sandbox

Um Anwendungsinhalt das sichere Cross-Scripting von Inhalt zu ermöglichen, der von außerhalb des Installationsverzeichnisses der Anwendung geladen wurde, können Sie Anwendungsinhalt mit dem frame - oder iframe -Element in die gleiche Sicherheits-Sandbox laden wie den externen Inhalt. Wenn das Cross-Scripting von Remoteinhalt nicht erforderlich ist, Sie eine Seite Ihrer Anwendung aber dennoch außerhalb der Anwendungs-Sandbox laden möchten, können Sie mit dem gleichen Verfahren http://localhost/ oder einen anderen unverfänglichen Wert als Herkunftsdomäne angeben.

AIR fügt dem frame-Element, mit dem Sie festlegen können, ob eine in das frame-Elemente geladene Anwendungsdatei einer anwendungsfremden Sandbox zugeordnet werden soll, die neuen Attribute sandboxRoot und documentRoot hinzu. In einen Pfad unterhalb der sandboxRoot -URL aufgelöste Dateien werden stattdessen aus dem Verzeichnis documentRoot geladen. Aus Sicherheitsgründen wird auf diese Weise geladener Anwendungsinhalt so behandelt, als sei er tatsächlich aus der sandboxRoot -URL geladen worden.

Die sandboxRoot -Eigenschaft gibt die URL an, mit der die Sandbox und Domäne bestimmt werden, in der der Frame-Inhalt abgelegt werden soll. Dazu muss das URL-Schema file: , http: oder https: verwendet werden. Wenn Sie eine relative URL angeben, verbleibt der Inhalt in der Anwendungs-Sandbox.

Die documentRoot -Eigenschaft gibt das Verzeichnis an, aus dem der Frame-Inhalt geladen wird. Dazu muss das URL-Schema file: , app: oder app: verwendet werden.

Das folgende Beispiel ordnet im Unterverzeichnis sandbox der Anwendung installierten Inhalt für die Ausführung in der Remote-Sandbox und der Domäne www.example.com zu:

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

Die Seite ui.html könnte mit folgendem Skript-Tag eine JavaScript-Datei aus dem lokalen Ordner sandbox laden:

<script src="http://www.example.com/local/ui.js"></script>

Mit einem Script-Tag wie dem Folgenden könnte sie ferner Inhalt aus einem Verzeichnis auf dem Remoteserver laden:

<script src="http://www.example.com/remote/remote.js"></script>

Die sandboxRoot -URL maskiert beliebigen Inhalt mit der gleichen URL auf dem Remoteserver. Im obigen Beispiel könnten Sie nicht auf Remoteinhalt unter www.example.com/local/ (oder den zugehörigen Unterverzeichnissen) zugreifen, denn AIR ordnet die Anforderung dem lokalen Anwendungsverzeichnis neu zu. Anforderungen werden neu zugeordnet, ganz gleich, ob sie von der Seitennavigation, einem XMLHttpRequest oder einem anderen Verfahren zum Laden von Inhalt abgeleitet wurden.

Einrichten einer Schnittstelle für Sandbox-Brücken

Sie können eine Sandbox-Brücke verwenden, wenn Inhalt in der Anwendungs-Sandbox auf Eigenschaften oder Methoden zugreifen muss, die von Inhalt in einer anwendungsfremden Sandbox definiert wurden, oder wenn anwendungsfremder Inhalt auf Eigenschaften und Methoden zugreifen muss, die von Inhalt in der Anwendungs-Sandbox definiert wurden. Erstellen Sie eine Brücke mit der childSandboxBridge - und der parentSandboxBridge -Eigenschaft des window -Objekts eines beliebigen untergeordneten Dokuments.

Einrichten untergeordneter Sandbox-Brücken

Die childSandboxBridge -Eigenschaft ermöglicht dem untergeordneten Dokument die Offenlegung einer Schnittstelle für Inhalt im übergeordneten Dokument. Um eine Schnittstelle offen zu legen, legen Sie für die childSandbox -Eigenschaft eine Funktion oder ein Objekt im untergeordneten Dokument fest. Dann können Sie über Inhalt im übergeordneten Dokument auf das Objekt bzw. die Funktion zugreifen. Das folgende Beispiel zeigt, wie ein in einem untergeordneten Dokument ausgeführtes Skript ein Objekt, das eine Funktion und eine Eigenschaft enthält, für das übergeordnete Dokument offenlegen kann:

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

Wenn dieser untergeordnete Inhalt in einen Inlineframe mit der zugewiesenen ID „child“ geladen wurde, könnten Sie durch Lesen der childSandboxBridge -Eigenschaft des Frames über den übergeordneten Inhalt auf die Schnittstelle zugreifen:

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

Einrichten übergeordneter Sandbox-Brücken

Die parentSandboxBridge -Eigenschaft ermöglicht dem übergeordneten Dokument die Offenlegung einer Schnittstelle für Inhalt im untergeordneten Dokument. Zum Offenlegen einer Schnittstelle legt das übergeordnete Dokument für die parentSandbox -Eigenschaft des untergeordneten Dokuments eine im übergeordneten Dokument definierte Funktion oder ein im übergeordneten Dokument definiertes Objekt fest. Dann können Sie über Inhalt im untergeordneten Dokument auf das Objekt bzw. die Funktion zugreifen. Das folgende Beispiel zeigt, wie ein im übergeordneten Frame ausgeführtes Skript ein Objekt offenlegen kann, das eine Funktion für ein untergeordnetes Dokument enthält:

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

Mit dieser Schnittstelle könnte Inhalt im untergeordneten Frame Text in der Datei save.txt speichern, hätte aber keinen anderen Zugriff auf das Dateisystem. Der untergeordnete Inhalt könnte die save-Funktion wie folgt aufrufen:

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

Anwendungsinhalt sollte eine möglichst schmale Schnittstelle für andere Sandboxen offenlegen. Anwendungsfremder Inhalt sollte als von Natur aus nicht vertrauenswürdig angesehen werden, denn er könnte versehentlich mit Code oder mit bösartigem Code injiziert worden sein. Um einen Missbrauch der Schnittstelle, die über die übergeordnete Sandbox-Brücke offen gelegt wurde, zu verhindern, müssen entsprechende Sicherheitsmaßnahmen getroffen werden.

Zugreifen auf eine übergeordnete Sandbox-Brücke beim Laden einer Seite

Damit ein Skript in einem untergeordneten Dokument auf eine übergeordnete Sandbox-Brücke zugreifen kann, muss die Brücke eingerichtet werden, bevor das Skript ausgeführt wird. Fenster-, Frame- und Inlineframe-Objekte lösen nach der Erstellung eines neuen Seiten-DOM, aber vor der Analyse von Skripts oder dem Hinzufügen von DOM-Elementen ein dominitialize -Ereignis aus. Mit diesem Ereignis können Sie die Brücke so früh in der Seitenerstellungsfolge erstellen, dass alle Skripts im untergeordneten Dokument auf sie zugreifen können.

Das folgende Beispiel illustriert die Erstellung einer übergeordneten Sandbox-Brücke als Reaktion auf ein vom untergeordneten Frame ausgelöstes dominitialize -Ereignis:

<html> 
<head> 
<script> 
var bridgeInterface = {}; 
bridgeInterface.testProperty = "Bridge engaged"; 
function engageBridge(){ 
    document.getElementById("sandbox").contentWindow.parentSandboxBridge = bridgeInterface; 
} 
</script> 
</head> 
<body> 
<iframe id="sandbox" 
            src="http://www.example.com/air/child.html"  
            documentRoot="app:/" 
            sandboxRoot="http://www.example.com/air/" 
            ondominitialize="engageBridge()"/> 
</body> 
</html>

Das folgende child.html -Dokument verdeutlicht, wie untergeordnete Inhalte auf die übergeordnete Sandbox-Brücke zugreifen können:

<html> 
    <head> 
        <script> 
            document.write(window.parentSandboxBridge.testProperty); 
        </script>   
    </head>   
    <body></body> 
</html>

Um statt in einem Frame in einem untergeordneten Fenster auf das dominitialize -Ereignis zu warten, müssen Sie den Listener dem neuen, von der window.open() -Funktion erstellten untergeordneten Fensterobjekt hinzufügen:

var childWindow = window.open(); 
childWindow.addEventListener("dominitialize", engageBridge()); 
childWindow.document.location = "http://www.example.com/air/child.html";

In diesem Fall ist es nicht möglich, Anwendungsinhalt einer anwendungsfremden Sandbox zuzuordnen. Dieses Verfahren ist nur sinnvoll, wenn child.html von außerhalb des Anwendungsverzeichnisses geladen wird. Sie können Anwendungsinhalt im Fenster auch weiterhin einer anwendungsfremden Sandbox zuordnen, müssen dazu allerdings zunächst eine Zwischenseite laden, die selbst Frames zum Laden des untergeordneten Dokuments verwendet, und es der gewünschten Sandbox zuordnen.

Wenn Sie mit der createRootWindow() -Funktion der HTMLLoader-Klasse ein Fenster erstellen, handelt es sich bei diesem nicht um ein untergeordnetes Fenster des Dokuments, aus dem createRootWindow() aufgerufen wird. Aus diesem Grund können Sie keine Sandbox-Brücke vom aufrufenden Fenster zu anwendungsfremdem Inhalt erstellen, der in das neue Fenster geladen wird. Stattdessen müssen Sie in dem neuen Fenster eine Zwischenseite laden, die zum Laden des untergeordneten Dokuments selbst Frames verwendet. Dann können Sie eine Brücke vom übergeordneten Dokument des neuen Fensters zum untergeordneten, in den Frame geladenen Dokument erstellen.