Перекрестное выполнение сценариев в содержимом из различных изолированных программных сред безопасности

Adobe AIR 1.0 и более поздних версий

Модель безопасности среды выполнения изолирует код из различных источников. Перекрестное выполнение сценариев содержимого в разных изолированных программных средах безопасности позволяет содержимому в одной из них обращаться к некоторым свойствам и методам в другой.

Защищенные изолированные программные среды AIR и код JavaScript

Политика AIR также основывается на определении происхождения, что не позволяет коду с одного домена обращаться к коду с другого. Все файлы помещаются в изолированные программные среды на основании своего происхождения. Как правило, содержимое в изолированной программной среде приложения не может нарушать этот принцип и выполнять перекрестное выполнение сценариев содержимого, загруженного извне установочного каталога приложения. Однако AIR предлагает несколько методов перекрестного выполнения сценариев содержимого вне приложения.

Один из методов использует фреймы и встроенные фреймы для привязки содержимого к защищенной изолированной программной среде. Все страницы, загружаемые из изолированной программной среды приложения, ведут себя так, будто бы они загружены с удаленного домена. Например, сопоставление содержимого приложения с доменом example.com позволяет перекрестное выполнение сценариев для страниц, загруженных с example.com.

Так как этот метод помещает содержимое приложения в другую изолированную программную среду, код в этом содержимом более не подчиняется ограничениям по выполнению кода в проверяемых строках. Техника сопоставления для изолированных программных сред позволяет снимать эти ограничения, даже если нет необходимости в перекрестном выполнении сценариев удаленного содержимого. Это особенно полезно при работе с одной из многочисленных инфраструктур JavaScript или с существующим кодом, который основывается на проверке строк. Однако необходимо помнить о дополнительных рисках внедрения и выполнения вредоносного содержимого при запуске содержимого вне изолированной программной среды приложения.

В то же время содержимое приложения, которое сопоставлено с другой изолированной программной средой, теряет доступ к API-интерфейсам AIR, поэтому техника сопоставления с изолированной программной средой не подходит для представления функциональности AIR коду, выполняемому вне изолированной программной среды приложения.

Еще один способ перекрестного выполнения сценариев позволяет создать интерфейс моста изолированной программной среды между содержимым в изолированной программной среде вне приложения и его родительским документом в изолированной программной среде приложения. Мост предоставляет дочернему содержимому доступ к свойствам и методам, заданным родителем, а родителю — доступ к свойствам и методам, заданным дочерним элементом (или и то и другое сразу).

Наконец, междоменные запросы XMLHttpRequest могут выполняться из изолированной программной среды приложения и из других изолированных программных сред (необязательно).

Дополнительные сведения см. в разделах « Элементы frame и iframe в HTML », « Безопасность HTML в Adobe AIR » и « Объект XMLHttpRequest ».

Загрузка содержимого приложения в изолированную программную среду вне приложения

Чтобы содержимое приложения могло выполнять безопасное перекрестное выполнение сценариев содержимого, загруженного из установочного каталога приложения, для загрузки содержимого приложения в ту же изолированную программную среду, что и внешнего содержимого, используется элемент frame или iframe . Если перекрестное выполнение сценариев удаленного содержимого не требуется, но требуется загрузить страницу приложения вне его изолированной программной среды, можно воспользоваться тем же способом и задать в качестве домена по умолчанию http://localhost/ или любое другое безопасное значение.

AIR добавляет в элемент frame новые атрибуты sandboxRoot и documentRoot , которые позволяют указать, нужно ли сопоставлять файл приложения, загруженный во фрейм, с изолированной программной средой вне приложения. Вместо этого файлы, указанные в URL-адресе sandboxRoot , загружаются в каталог documentRoot . Из соображений безопасности содержимое приложения, загружаемое таким способом, обрабатывается так, будто оно загружено из URL-адреса sandboxRoot .

Свойство sandboxRoot задает URL-адрес для определения изолированной программной среды и домена, куда следует поместить содержимое. Следует использовать схему URL-адресов file: , http: или https: . При указании относительного URL-адреса содержимое остается в изолированной программной среде приложения.

Свойство documentRoot указывает каталог, из которого загружается содержимое фрейма. Следует использовать схему URL-адресов file: , app: или app-storage: .

В примере ниже содержимое, установленное в подкаталог приложения sandbox , предназначено для запуска в удаленной изолированной программной среде и домене www.example.com :

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

Страница ui.html может загружать файл javascript из локальной папки sandbox с помощью следующего тега:

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

Содержимое также может загружаться из каталога на удаленном сервере с помощью тега script, как показано ниже:

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

URL sandboxRoot маскирует все содержимое с этого же URL-адресу на удаленном сервере. В предыдущем примере доступ к удаленному содержимому на домене www.example.com/local/ (или любом из его подкаталогов) запрещен, так как AIR повторно сопоставляет запросы с локальным каталогом приложения. Запросы сопоставляются повторно независимо от того, какой способ загрузки содержимого вызывает их: навигация по странице, запрос XMLHttpRequest или любой другой.

Настройка интерфейса моста изолированной программной среды

Мост изолированной программной среды может использоваться, когда необходим доступ к свойствам или методам в изолированной программной среде вне приложения или когда содержимое вне приложения должно обращаться к свойствам и методам, определенным содержимым изолированной программной среды приложения. Используйте свойства childSandboxBridge и parentSandboxBridge для создания объекта window любого дочернего документа.

Установка моста дочерней изолированной программной среды

Свойство childSandboxBridge позволяет дочернему документу предоставлять интерфейс содержимому родительского документа. Для этого задайте в качестве значения свойства childSandbox функцию или объект в дочернем документе. После этого объект или функция будут доступны из содержимого родительского документа. В примере ниже показан сценарий, выполняемый в дочернем документе, который предоставляет своему родителю объект, содержащий функцию и свойство:

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

Если дочернее содержимое загружается во встроенный фрейм, у которого есть id «child», то доступ к интерфейсу из родительского содержимого осуществляется путем чтения свойства фрейма childSandboxBridge :

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

Установка моста родительской изолированной программной среды

Свойство parentSandboxBridge позволяет родительскому документу предоставлять интерфейс содержимому дочернего документа. Для этого в качестве значения свойства parentSandbox дочернего документа назначается функция или объект в родительском документе. После этого объект или функция будут доступны из содержимого дочернего элемента. В примере ниже показан сценарий, выполняемый в родительском фрейме, который предоставляет своему дочернему элементу объект, содержащий функцию:

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

С помощью этого интерфейса содержимое в дочернем фрейме может сохранять текст в файл save.txt , но других способов доступа к файловой системе у него нет. Дочернее содержимое может вызывать функцию сохранения следующим образом:

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

Содержимое приложения должно предоставлять другим изолированным программным средам максимально строгий интерфейс. Содержимое вне приложения следует расценивать как небезопасное, потому что оно может подвергаться случайному или злонамеренному внедрению кода. Для защиты от злонамеренного использования интерфейса, который предоставляется через мост родительской изолированной программной среды следует пользоваться соответствующими мерами безопасности.

Доступ к мосту родительской изолированной программной среды во время загрузки страницы

Чтобы код дочернего документа имел доступ к мосту родительской изолированной программной среды, необходимо установить мост до того, как начнет выполняться сценарий. Объекты window, frame и iframe отправляют событие dominitialize после создания новой модели DOM для страницы, но до разбора какого-либо сценария или добавления элементов DOM. Событие dominitialize позволяет установить мост для создания объектов на раннем этапе построения страницы, чтобы все сценарии дочернего документа могли к ним обратиться.

В примере ниже показано, как создать мост родительской изолированной программной среды в ответ на событие dominitialize , отправляемое из дочернего фрейма:

<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>

В следующем документе child.html показано, как содержимое дочерней изолированной программной среды может получать доступ к мосту родительской:

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

Чтобы прослушивать событие dominitialize в дочернем окне, а не во фрейме, следует добавить прослушиватель новому дочернему объекту window, который создан функцией window.open() :

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

В этом случае содержимое приложения не может быть сопоставлено с изолированной программной средой вне приложения. Этот метод подходит только для случаев, когда страница child.html загружается извне каталога приложения. Содержимое приложения в окне по-прежнему может быть сопоставлено с изолированной программной средой вне приложения, но для этого сначала нужно загрузить промежуточную страницу, которая также использует фреймы для загрузки дочернего документа, и сопоставить ее с нужной изолированной программной средой.

Если для создания окна используется функция createRootWindow() класса HTMLLoader, новое окно не становится дочерним элементом документа, из которого вызывается функция createRootWindow() . Таким образом, мост изолированной программной среды не может быть создан между вызывающим окном и содержимым вне приложения, загружаемым в новое окно. Вместо этого следует загрузить в новом окне промежуточную страницу, которая использует фреймы для загрузки дочернего содержимого. Можно установить мост от родительского документа нового окна к дочернему документу, загружаемому во фрейм.