Безопасность HTML в Adobe AIR

Adobe AIR 1.0 и более новых версий

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

Среда выполнения реализует правила и предоставляет механизмы для преодоления возможных проблем безопасности в HTML и JavaScript. Те же правила применяются к приложению, исходно написанному на JavaScript, и при загрузке содержимого HTML и JavaScript в приложение на базе SWF. Содержимое в изолированной программной среде приложения и в других изолированных программных средах имеют разные привилегии. При загрузке содержимого во встроенный или обычный кадр среда выполнения реализует безопасный механизм моста изолированной программной среды, который позволяет содержимому во встроенном или обычном кадре безопасно обмениваться данными с содержимым в изолированной программной среде безопасности приложения.

AIR SDK содержит три класса для визуализации HTML-содержимого.

Класс HTMLLoader обеспечивает плотную интеграцию кода JavaScript и API-интерфейсов AIR.

Класс StageWebView — это класс визуализации HTML, и он обеспечивает крайне ограниченную интеграцию с домашним приложением AIR. Содержимое, загружаемое классом StageWebView, никогда не помещается в изолированную программную среду приложения, не имеет доступа к данным и не может вызывать функции домашнего приложения AIR. В платформах для настольных систем класс StageWebView использует встроенный HTML-механизм AIR, построенный на основе Webkit, который также используется классом HTMLLoader. В мобильных платформах класс StageWebView использует механизм управления HTML, предоставленный операционной системой. Таким образом, на мобильных платформах при использовании класса StageWebView действуют такие же требования безопасности и возникают аналогичные проблемы безопасности, какие существуют в системном веб-браузере.

Класс TextField может отображать строки текста HTML. Выполнение сценариев JavaScript невозможно, но текст может содержать ссылки и загруженные извне изображения.

Дополнительные сведения см. в разделе «Избежание ошибок безопасности в JavaScript».

Обзор конфигурации приложения на базе HTML

Кадры и встроенные кадры обеспечивают удобную структуру организации содержимого HTML в AIR. Кадры позволяют поддерживать сохраняемость данных и безопасно работать с удаленным содержимым.

Поскольку HTML в AIR сохраняет обычную постраничную структуру, окружение HTML полностью обновляется, если верхний кадр содержимого HTML «переходит» на другую страницу. При помощи кадров и встроенных кадров можно поддерживать сохраняемость данных в AIR, как и в случае с веб-приложением, выполняющимся в обозревателе. Определение основных объектов приложения в верхнем кадре позволит им сохраниться до перехода кадра на новую страницу. При помощи дочерних или встроенных кадров можно загружать и отображать переходные части приложения. (Существует несколько способов поддержания сохраняемости данных, которые можно использовать в дополнение к кадрам или вместо них. К ним относятся файлы cookie, локальные общие объекты, локальное хранилище файлов, зашифрованное хранилище файлов и локальное хранилище базы данных.)

Поскольку HTML в AIR занимает свое обычное промежуточное положение между исполняемым кодом и данными, AIR размещает содержимое в верхнем кадре среды HTML в изолированной программной среде приложения. После передачи события load для страницы AIR ограничивает любые действия, такие как eval(), которые могут преобразовать текстовую строку в исполняемый объект. Это ограничение действует, даже если приложение не загружает удаленное содержимое. Чтобы разрешить HTML-содержимому выполнять эти запрещенные операции, необходимо использовать кадры или встроенные кадры, чтобы поместить содержимое в изолированную программную среду вне приложения. (Выполнение содержимого в дочернем кадре изолированной программной среды может быть необходимо при использовании некоторых прикладных структур JavaScript, основанных на функции eval().) Полный перечень ограничений, распространяющихся на JavaScript в изолированной программной среде приложения, см. в разделе Ограничения по использованию кода в содержимом из различных изолированных программных сред.

Поскольку HTML в AIR сохраняет способность загружать удаленное, возможно, небезопасное содержимое, AIR реализует стратегию «одинакового источника», которая предотвращает взаимодействие содержимого из одного домена с содержимым из другого. Чтобы разрешить взаимодействие содержимого приложения и содержимого из другого домена, можно создать мост в качестве интерфейса между родительским и дочерним кадром.

Отношения между родительской и дочерней изолированными программными средами

AIR добавляет атрибуты sandboxRoot и documentRoot в элементы HTML frame и iframe. Эти атрибуты позволяют воспринимать содержимое приложения так, будто оно загружено из другого домена:

Атрибут

Описание

sandboxRoot

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

documentRoot

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

Следующий пример преобразует содержимое, установленное в подкаталоге изолированной программной среды приложения, для выполнения в удаленной изолированной программной среде и домене www.example.com:

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

Создание моста между родительским и дочерним кадрами из различных изолированных программных сред или доменов

AIR добавляет свойства childSandboxBridge и parentSandboxBridge для объекта window любого дочернего кадра. Эти свойства позволяют задать мосты в качестве интерфейсов между родительским и дочерним кадрами. Каждый мост работает в одном направлении:

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

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

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

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

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

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

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

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

Если дочернее содержимое пытается задать свойство объекта parentSandboxBridge, среда выполнения выдает исключение SecurityError. Если родительское содержимое пытается задать свойство объекта childSandboxBridge, среда выполнения выдает исключение SecurityError.

Ограничения по использованию кода в содержимом из различных изолированных программных сред

Как было сказано во введении к данной теме, Безопасность HTML в Adobe AIR, среда выполнения реализует правила и предоставляет механизмы для преодоления возможных проблем безопасности в HTML и JavaScript. В данном разделе описываются подобные ограничения. При попытке кода вызвать API-интерфейсы с ограниченным доступом среда выполнения выдает ошибку с сообщением «Нарушение защиты среды выполнения Adobe AIR со стороны кода JavaScript в изолированной программной среде безопасности приложения».

Дополнительные сведения см. в разделе «Избежание ошибок безопасности в JavaScript».

Ограничения по использованию функции JavaScript eval() и подобных методов

На содержимое HTML в изолированной программной среде безопасности приложения распространяются ограничения по использованию API-интерфейсов, которые могут динамически преобразовывать строки в исполняемый код после загрузки кода (после отправки события onload элемента body и завершения выполнении функции обработчика onload). Это предотвращает случайный ввод (и исполнение) приложением кода из источников, не относящихся к приложению (например, из потенциально небезопасных сетевых доменов).

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

Одно из ограничений касается использования функции JavaScript eval(). После загрузки кода из изолированной программной среды приложения и завершения работы обработчика события onload использование функции eval() становится ограниченным. Использование функции eval()после загрузки кода из изолированной программной среды безопасности приложения подчиняется следующим правилам:

  • Допускается использование выражений с литералами. Например:

    eval("null"); 
    eval("3 + .14"); 
    eval("'foo'");
  • Допускается использование литералов объектов. Например:

    { prop1: val1, prop2: val2 }
  • Функции установщика/получателя литералов объектов запрещены. Например:

    { get prop1() { ... }, set prop1(v) { ... } }
  • Допускается использование литералов массивов, например:

    [ val1, val2, val3 ]
  • Выражения, включающие в себя считывание свойств, запрещены. Например:

    a.b.c
  • Вызов функций запрещен.

  • Определения функций запрещены.

  • Задание свойств запрещено.

  • Литералы функций запрещены.

Однако во время загрузки кода, до отправки события onload и завершения выполнения функции обработчика события onload, эти ограничения не действуют для содержимого в изолированной программной среде безопасности приложения.

Например, после того как код уже загружен, при выполнении следующего кода среда выполнения выдает исключение:

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

Динамически создаваемый код, как, например, тот, что создается при вызове функции eval(), представляет собой угрозу безопасности, будучи разрешенным в изолированной программной среде приложения. Например, приложение может случайно выполнить строку, загруженную с сетевого домена и содержащую зловредный код. Это может быть код, который удалит или изменит файлы на компьютере пользователя. Или код, передающий данные о содержимом локального файла недоверенному сетевому домену.

Генерирование динамического кода может осуществляться следующим образом:

  • Вызов функции eval().

  • Использование свойств innerHTML или функций DOM для вставки тегов сценариев, которые загружают сценарий вне каталога приложения.

  • Использование свойств innerHTML или функций DOM для вставки тегов сценариев со встроенным кодом (вместо загрузки сценария при помощи атрибута src).

  • Задание атрибута src для тегов script для загрузки файла JavaScript, находящегося вне каталога приложения.

  • Использование схемы URL-адресов javascript (как в href="javascript:alert('Test')").

  • Использование функции setInterval() или setTimout() в случаях, когда первый параметр (задающий асинхронное выполнение функции) является строкой (для вычисления), а не именем функции (как в setTimeout('x = 4', 1000)).

  • Вызов document.write() или document.writeln().

Код в изолированной программной среде безопасности приложения может использовать только эти методы во время загрузки содержимого.

Эти ограничения не запрещают использование eval() с литералами объектов JSON. Это позволяет содержимому приложения работать с библиотекой JavaScript формата JSON. Однако нельзя использовать перегруженный код JSON (с обработчиками событий).

Для других платформ Ajax и библиотек кода JavaScript проверьте, работает ли код платформы или библиотеки при ограничениях, распространяющихся на динамически генерируемые коды. Если коды не работают, поместите любое содержимое, которое использует платформу или библиотеку, в изолированную программную среду, отличную от изолированной программной среды приложения. Дополнительные сведения см. в разделах «Ограничения для JavaScript внутри AIR» и «Выполнение сценариев между содержимым приложения и другим содержимым». Список платформ Ajax, которые поддерживают изолированную программную среду безопасности приложения, приведен на сайте Adobe http://www.adobe.com/products/air/develop/ajax/features/.

В отличие от содержимого в изолированной программной среде безопасности приложения содержимое JavaScript из других изолированных программных сред безопасности может вызвать функцию eval() для исполнения динамически генерируемого кода в любое время.

Ограничения доступа к API-интерфейсам AIR (для изолированных программных сред вне приложения)

Код JavaScript в изолированной программной среде безопасности, отличной от изолированной программной среды приложения, не имеет доступа к объекту window.runtime, поэтому не может исполнять API-интерфейсы AIR. Если содержимое в изолированной программной среде, отличной от изолированной программной среды приложения, вызывает следующий код, приложение выдает исключение TypeError:

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

Исключение относится к типу TypeError (с неопределенным значением), поскольку содержимое в такой изолированной программной среде не распознает объект window.runtime, поэтому он воспринимается как неопределенный.

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

Ограничения на вызов XMLHttpRequest

Содержимое HTML в изолированной программной среде безопасности приложения не может использовать синхронные методы XMLHttpRequest для загрузки данных из источников вне изолированной программной среды приложения во время загрузки содержимого HTML и события onLoad.

По умолчанию содержимое HTML в изолированных программных средах, отличных от изолированной программной среды приложения, не может использовать объект JavaScript XMLHttpRequest для загрузки данных из доменов, отличных от домена, вызывающего запрос. Теги frame или iframe могут включать в себя атрибут allowcrosscomainxhr. Установка для этого атрибута любого другого значения кроме значения null позволяет содержимому в кадре или во встроенном кадре использовать объект JavaScript XMLHttpRequest для загрузки данных из доменов, отличных от домена кода, вызывающего запрос:

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

Дополнительные сведения см. в разделе «Выполнение сценариев между содержимым из различных доменов».

Ограничения по загрузке элементов CSS, frame, iframe и img (для содержимого в изолированных программных средах вне приложения)

Содержимое HTML в удаленных (сетевых) изолированных программных средах может загружать содержимое CSS, frame, iframe и img только из удаленных изолированных программных сред (с сетевых URL-адресов).

Содержимое HTML в локальной изолированной программной среде файловой системы, локальной изолированной программной среде с сетевым подключением или в локальной доверенной изолированной программной среде может загружать содержимое CSS, frame, iframe и img только из локальных изолированных программных сред (не из изолированных программных сред приложения или удаленных изолированных программных сред).

Ограничения по вызову метода JavaScript window.open()

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

Содержимое не из изолированных программных сред приложения может успешно вызвать метод JavaScript window.open() только в ответ на событие, инициированное вводом с мыши или клавиатуры. Это предотвращает создание содержимым, не относящимся к приложению, окон, используемых с целью мошенничества (например, с целью информационных атак). Кроме того, обработчик событий мыши или клавиатуры не может задать выполнение метода window.open() после задержки (например, вызвав функцию setTimeout()).

Содержимое HTML в изолированных программных средах remote (сетевых) может использовать метод window.open() только для открытия содержимого в удаленных сетевых изолированных программных средах. Оно не может использовать метод window.open() для открытия содержимого из изолированной программной среды приложения или локальных изолированных программных сред.

Содержимое в локальной изолированной программной среде файловой системы, локальной изолированной программной среде с сетевым подключением или в локальной доверенной изолированной программной среде (см. раздел «Изолированные программные среды») может использовать метод window.open() только для открытия содержимого в локальных изолированных программных средах. Оно не может использовать метод window.open() для открытия содержимого из изолированной программной среды приложения или изолированной программной среды remote.

Ошибки при вызове кода с ограниченным доступом

При вызове кода, который нельзя использовать в изолированной программной среде ввиду ограничений безопасности, среда выполнения выдает ошибку JavaScript: «Нарушение защиты среды выполнения Adobe AIR со стороны кода JavaScript в изолированной программной среде безопасности приложения».

Дополнительные сведения см. в разделе «Избежание ошибок безопасности в JavaScript».

Защита изолированной программной среды при загрузке HTML-содержимого из строки

Метод loadString() класса HTMLLoader позволяет создавать HTML-содержимое во время выполнения. Однако данные, используемые в качестве HTML-содержимого, могут быть повреждены, если они будут загружаться из незащищенного источника в Интернете. По этой причине по умолчанию HTML-содержимое, созданное с помощью метода loadString(), не помещается в изолированную программную среду приложения и не имеет доступа к прикладным интерфейсам программирования AIR. Но можно установить для свойства placeLoadStringContentInApplicationSandbox объекта HTMLLoader значение true, чтобы размещать HTML-содержимое, созданное методом loadString(), в изолированную программную среду приложения. Дополнительные сведения см. в разделе «Загрузка HTML-содержимого из строки».