Este tópico descreve a arquitetura de segurança HTML do AIR e como usar iframes, quadros e a ponte da caixa de proteção para configurar aplicativos baseados em HTML e integrar conteúdo HTML com segurança em aplicativos baseados em SWF.
O tempo de execução aplica regras e oferece mecanismos para dominar possíveis vulnerabilidades de segurança em HTML e JavaScript. As mesmas regras são aplicadas se o aplicativo for gravado principalmente em JavaScript ou se você carregar conteúdo HTML e JavaScript em um aplicativo baseado em SWF. Conteúdo na caixa de proteção do aplicativo e a caixa de proteção de segurança que não seja de aplicativo têm privilégios distintos. Ao carregar o conteúdo em um iframe ou frame, o tempo de execução fornece um mecanismo de
ponte de caixa de proteção
seguro, que permite que o conteúdo frame ou iframe se comunique de maneira segura com o conteúdo na caixa de proteção de segurança do aplicativo.
O SDK do AIR oferece três classes para renderização de conteúdo HTML.
A classe HTMLLoader proporciona integração entre o código JavaScript e as APIs do AIR.
A classe StageWebView é uma classe de renderização de HTML e tem integração muito limitada com o aplicativo do AIR host. O conteúdo carregado pela classe StageWebView nunca é colocado na caixa de proteção de segurança do aplicativo e não pode acessar dados nem chamar funções no aplicativo do AIR host. Em plataformas de desktop, a classe StageWebView usa o mecanismo HTML incorporado do AIR, com base no Webkit, que também é usado pela classe HTMLLoader. Em plataformas móveis, a classe StageWebView usa o controle HTML fornecido pelo sistema operacional. Assim, em plataformas móveis, a classe StageWebView tem as mesmas considerações e vulnerabilidades de segurança do navegador da Web do sistema.
A classe TextField pode exibir strings de texto em HTML. Nenhum JavaScript pode ser executado, mas o texto pode incluir links e imagens carregadas externamente.
Para obter mais informações, consulte
Como evitar erros JavaScript relacionados à segurança
.
Visão geral sobre a configuração de aplicativo baseado em HTML
Os Frames e iframes oferecem uma estrutura conveniente para organizar conteúdo HTML no AIR. Os frames oferecem um meio de manter a persistência de dados e trabalhar de maneira segura com conteúdo remoto.
Como o HTML no AIR retém sua organização normal baseada em página, o ambiente HTML será totalmente atualizado, caso o frame superior do conteúdo HTML "navegue" para uma página diferente. Você pode usar frames e iframes para manter a persistência de dados no AIR, da mesma maneira que em um aplicativo da Web em execução em um navegador. Defina os objetos principais do aplicativo no frame superior e eles persistirão, desde que você não permita que o frame navegue para uma nova página. Use frames ou iframes filhos para carregar e exibir as partes transitórias do aplicativo. (Há diversas maneiras de manter a persistência de dados, que podem ser usadas além de ou em vez de frames. Isso inclui cookies, objetos locais compartilhados, armazenamento local de arquivos, depósito de arquivo criptografado e armazenamento de banco de dados local).
Como o HTML no AIR retém sua linha desfocada normal entre o código executável e os dados, o AIR coloca o conteúdo no quadro superior do ambiente HTML, na caixa de proteção do aplicativo. Depois do evento
load
da página, o AIR restringe quaisquer operações, como
eval()
, que possam converter uma sequência de caracteres de texto em um objeto executável. Essa restrição é aplicada mesmo quando o aplicativo não carrega conteúdo remoto. Para permitir que o conteúdo em HTML execute essas operações restritas, você deve usar frames ou iframes para colocar o conteúdo em uma caixa de proteção não aplicativo. (Executar conteúdo em um quadro filho de uma caixa de proteção pode ser necessário ao usar algumas estruturas do aplicativo JavaScript que dependem da função
eval()
.) Para obter uma lista completa das restrições JavaScript na caixa de proteção do aplicativo, consulte
Restrições de código de conteúdo em caixas de proteção distintas
.
Como o HTML no AIR mantém a capacidade de carregar conteúdo remoto possivelmente inseguro, o AIR aplica a política de mesma origem que impede que o conteúdo de um domínio interaja com o conteúdo de outro domínio. Para permitir a interação entre o conteúdo do aplicativo e o conteúdo de outro domínio, você pode configurar uma ponte para servir como interface entre um frame pai e filho.
Configuração de relacionamento pai-filho de caixa de proteção
O AIR adiciona os atributos
sandboxRoot
e
documentRoot
aos elementos frame e iframe de HTML. Esses atributos permitem tratar o conteúdo do aplicativo como se ele tivesse vindo de outro domínio:
Atributo
|
Descrição
|
sandboxRoot
|
A URL que deve ser usada para determinar a caixa de proteção e o domínio em que o conteúdo do frame deve ser colocado. Os esquemas de URL
file:
,
http:
ou
https:
devem ser usados.
|
documentRoot
|
A URL da qual o conteúdo do frame deve ser carregado. Os esquemas de URL
file:
,
app:
ou
app-storage:
devem ser usados.
|
O exemplo a seguir mapeia o conteúdo instalado no subdiretório da caixa de proteção do aplicativo a ser executado na caixa de proteção remota e o domínio www.exemplo.com:
<iframe
src="ui.html"
sandboxRoot="http://www.example.com/local/"
documentRoot="app:/sandbox/">
</iframe>
Configuração de ponte entre frames pai e filho em caixas de proteção ou domínios distintos
O AIR adiciona as propriedades
childSandboxBridge
e
parentSandboxBridge
ao objeto
window
de qualquer frame filho. Essas propriedades permitem definir pontes para servir como interfaces entre um quadro pai e filho. Cada ponte segue em uma direção:
childSandboxBridge
A propriedade
childSandboxBridge
permite que o frame filho exponha uma interface para o conteúdo do frame pai. Para expor uma interface, você define a propriedade
childSandbox
como função ou objeto no frame filho. Em seguida, você pode acessar o objeto ou a função do conteúdo no frame pai. O exemplo a seguir mostra como um script que está sendo executado em um frame filho pode expor um objeto contendo uma função e uma propriedade para o respectivo pai:
var interface = {};
interface.calculatePrice = function(){
return .45 + 1.20;
}
interface.storeID = "abc"
window.childSandboxBridge = interface;
Se esse conteúdo filho estiver em um iframe com
id
de
"child"
atribuída, você poderá acessar a interface do conteúdo pai, lendo a propriedade
childSandboxBridge
do frame:
var childInterface = document.getElementById("child").childSandboxBridge;
air.trace(childInterface.calculatePrice()); //traces "1.65"
air.trace(childInterface.storeID)); //traces "abc"
parentSandboxBridge
A propriedade
parentSandboxBridge
permite que o frame pai exponha uma interface para o conteúdo do frame filho. Para expor uma interface, você define a propriedade
parentSandbox
do frame filho como função ou objeto no frame pai. Em seguida, você pode acessar o objeto ou a função do conteúdo no frame filho. O exemplo a seguir mostra como um script em execução no frame pai pode expor um objeto contendo uma função save para o filho:
var interface = {};
interface.save = function(text){
var saveFile = air.File("app-storage:/save.txt");
//write text to file
}
document.getElementById("child").parentSandboxBridge = interface;
Ao usar essa interface, o conteúdo no frame filho poderá salvar texto em um arquivo chamado save.txt. No entanto, ele não terá nenhum outro acesso ao sistema de arquivos. Em geral, o conteúdo do aplicativo deve expor a interface mais estreita possível para as outras caixas de proteção. O conteúdo filho poderá chamar a função save da seguinte maneira:
var textToSave = "A string.";
window.parentSandboxBridge.save(textToSave);
Se o conteúdo filho tentar definir uma propriedade do objeto
parentSandboxBridge
, o tempo de execução lançará uma exceção SecurityError. Se o conteúdo pai tentar definir uma propriedade do objeto
childSandboxBridge
, o tempo de execução lançará uma exceção SecurityError.
Restrições de código de conteúdo em caixas de proteção distintas
Como discutido na introdução deste tópico,
Segurança HTML no Adobe AIR
, o tempo de execução aplica regras e fornece mecanismos para dominar possíveis vulnerabilidades de segurança em HTML e JavaScript. Este tópico lista essas restrições. Se o código tentar chamar essas APIs restritas, o tempo de execução lançará um erro com a mensagem "Violação de segurança de tempo de execução do Adobe AIR para código JavaScript na caixa de proteção de segurança do aplicativo".
Para obter mais informações, consulte
Como evitar erros JavaScript relacionados à segurança
.
Restrições sobre o uso da função eval() de JavaScript e técnicas semelhantes
Para conteúdo HTML na caixa de proteção de segurança do aplicativo há limitações no uso das APIs que podem transformar dinamicamente as strings em código executável após o carregamento do código (após o evento
onload
do elemento
body
ter sido despachado e o término de execução da função do manipulador
onload
). Isso é para evitar que o aplicativo injete inadvertidamente (e execute) código de fontes "não aplicativo" (como domínios de rede potencialmente inseguros).
Por exemplo, se o aplicativo usa strings de dados de uma fonte remota para gravar na propriedade innerHTML de um elemento DOM, a string pode incluir o código (JavaScript) executável que pode executar operações inseguras. No entanto, enquanto o conteúdo estiver carregando, não há risco de inserir strings remotas no DOM.
Uma restrição está no uso da função
eval()
de JavaScript. Após o código na caixa de proteção do aplicativo tiver sido carregado e após o processamento do manipulador de eventos onload, você só poderá usar a função
eval()
de forma limitada. As seguintes regras se aplicam ao uso da função
eval()
após
o código ter sido carregado da caixa de proteção de segurança do aplicativo:
-
São permitidas expressões que envolvem literais. Por exemplo:
eval("null");
eval("3 + .14");
eval("'foo'");
-
As literais de objeto são permitidos da seguinte maneira:
{ prop1: val1, prop2: val2 }
-
As opções setter/getters de literal de objeto são
proibidas
, conforme segue:
{ get prop1() { ... }, set prop1(v) { ... } }
-
As literais de matriz são permitidas da seguinte maneira:
[ val1, val2, val3 ]
-
Expressões que envolvem leituras de propriedades são
proibidas
, conforme segue:
a.b.c
-
A chamada de função é
proibida
.
-
Definições de função são
proibidas.
-
A configuração de qualquer propriedade é
proibida
.
-
As literais de função são
proibidas
.
No entanto, enquanto o código estiver sendo carregado, antes do evento
onload
e durante a execução da função do manipulador de eventos
onload
, essas restrições não serão aplicadas ao conteúdo na caixa de proteção de segurança do aplicativo.
Por exemplo, após o código ser carregado, o código a seguir resultará no lançamento de uma exceção pelo tempo de execução.
eval("alert(44)");
eval("myFunction(44)");
eval("NativeApplication.applicationID");
O código gerado dinamicamente, como o que é feito durante a chamada da função
eval()
, representaria um risco à segurança se permitido na caixa de proteção do aplicativo. Por exemplo, um aplicativo pode executar inadvertidamente uma string carregada de um domínio de rede e essa string pode conter código mal-intencionado. Por exemplo, esse pode ser um código de exclusão ou alteração de arquivos no computador do usuário. Ou pode ser um código que informa o conteúdo de um arquivo local para um domínio de rede não confiável.
As formas de gerar código dinâmico são as seguintes:
-
Chamando a função
eval()
.
-
Uso de propriedades
innerHTML
ou funções DOM para inserir tags de script que carregam um script de fora do diretório do aplicativo.
-
Uso de propriedades
innerHTML
ou funções DOM para inserir tags de scripts com código inline (em vez de carregar um script através do atributo
src
).
-
Configuração do atributo
src
para que a tag de
script
carregue um arquivo JavaScript que está fora do diretório do aplicativo.
-
Uso de esquema de URL
javascript
(como em
href="javascript:alert('Test')"
).
-
Uso da função
setInterval()
ou
setTimout()
em que o primeiro parâmetro (que define a função para ser executada de forma assíncrona) é uma string (a ser avaliada) em vez de um nome de função (como em
setTimeout('x = 4', 1000)
).
-
Chamada de
document.write()
ou
document.writeln()
.
O código na caixa de proteção de segurança do aplicativo só pode usar esses métodos enquanto o conteúdo estiver sendo carregado.
Essas restrições
não
impedem o uso de
eval()
com literais do objeto JSON. Isso permite que o conteúdo do aplicativo trabalhe com a biblioteca JavaScript JSON. No entanto, você não poderá usar código JSON sobrecarregado (com manipuladores de eventos)
Em outras estruturas Ajax e bibliotecas de código JavaScript, certifique-se de que o código na estrutura ou biblioteca funciona dentro dessas restrições em código gerado dinamicamente. Se não funcionarem, inclua algum conteúdo que use a estrutura ou biblioteca em uma caixa de proteção de segurança "não aplicativo". Consulte detalhes em
Restrições a JavaScript dentro do AIR
e
Script entre conteúdo de aplicativo e "não aplicativo"
. O Adobe mantém uma lista das estruturas Ajax conhecidas por oferecer suporte à caixa de proteção de segurança do aplicativo, em
http://www.adobe.com/products/air/develop/ajax/features/
.
Ao contrário do conteúdo na caixa de proteção de segurança do aplicativo, o conteúdo JavaScript em uma caixa de proteção de segurança "não aplicativo"
pode
chamar a função
eval()
para executar código gerado dinamicamente a qualquer momento.
Restrições de acesso às APIs do AIR (para caixas de proteção que não são de aplicativo)
O código JavaScript em uma caixa de proteção "não aplicativo" não tem acesso ao objeto
window.runtime
e, portanto, esse código não pode executar APIs do AIR. Se o conteúdo em uma caixa de proteção de segurança "não aplicativo" chamar o código a seguir, o aplicativo lançará uma exceção TypeError:
try {
window.runtime.flash.system.NativeApplication.nativeApplication.exit();
}
catch (e)
{
alert(e);
}
O tipo de exceção é TypeError (valor indefinido), porque o conteúdo na caixa de proteção "não aplicativo" não reconhece o objeto
window.runtime
, portanto, ele é considerado como valor indefinido.
Você pode expor a funcionalidade de tempo de execução ao conteúdo em uma caixa de proteção "não aplicativo" usando uma ponte de script. Para obter detalhes, consulte
Script entre conteúdo de aplicativo e "não aplicativo"
.
Restrições no uso de chamadas XMLHttpRequest
O conteúdo HTML na caixa de proteção de segurança do aplicativo não pode usar os métodos XMLHttpRequest síncronos para carregar dados de fora da caixa de proteção do aplicativo enquanto o conteúdo HTML estiver sendo carregado e durante o evento
onLoad
.
Por padrão, o conteúdo HTML nas caixas de proteção de segurança "não aplicativo" não têm permissão para usar o objeto XMLHttpRequest de JavaScript para carregar dados de outros domínios que não o domínio que está chamando a solicitação. A tag
frame
ou
iframe
pode incluir um atributo
allowcrosscomainxhr
. Configurar esse atributo com qualquer valor diferente de "null" permite que o conteúdo no frame ou iframe use o objeto XMLHttpRequest de Javascript para carregar dados de outros domínios que não sejam o domínio do código que está chamando a solicitação:
<iframe id="UI"
src="http://example.com/ui.html"
sandboxRoot="http://example.com/"
allowcrossDomainxhr="true"
documentRoot="app:/">
</iframe>
Para obter mais informações, consulte
Script entre conteúdos em domínios distintos
.
Restrições no carregamento de elementos CSS, frame, iframe e img (para conteúdo em caixas de proteção que não são de aplicativo)
O conteúdo HTML nas caixas de proteção de segurança remota (rede) pode carregar apenas conteúdo CSS,
frame
,
iframe
e
img
de caixas de proteção remotas (de URLs de rede).
O conteúdo HTML nas caixas de proteção local com sistema de arquivos, local com rede ou local confiável só podem carregar conteúdo CSS, frame, iframe e
img
de caixas de proteção locais (e não de caixas de proteção de aplicativo ou remotas).
Restrições na chamada do método window.open() de JavaScript
Se a janela criada através de uma chamada para o método
window.open()
de JavaScript exibir conteúdo de uma caixa de proteção de segurança "não aplicativo", o título da janela iniciará com o título da janela principal (inicializada), seguido pelo caractere dois pontos. Você não pode usar código para remover da tela essa parte do título da janela.
O conteúdo nas caixas de proteção de segurança "não aplicativo" só consegue chamar com êxito o método
window.open()
de JavaScript em resposta a um evento acionado pelo mouse do usuário ou pela interação do teclado. Isso evita que o conteúdo "não aplicativo" crie janelas que possam ser usadas de maneira enganosa (por exemplo, em ataques de phishing). Além disso, o manipulador de eventos do evento de mouse ou teclado não pode configurar o método
window.open()
para ser executado após um atraso (por exemplo, chamando a função
setTimeout()
).
O conteúdo nas caixas de proteção remotas (rede) só podem usar o método
window.open()
para abrir o conteúdo nas caixas de proteção de rede remota. Ele não pode usar o método
window.open()
para abrir o conteúdo das caixas de proteção locais ou do aplicativo.
O conteúdo nas caixas de proteção local com sistema de arquivos, local com rede ou local confiável (consulte
Caixas de proteção de segurança
) só pode usar o método
window.open()
para abrir o conteúdo nas caixas de proteção locais. Ele não pode usar o método
window.open()
para abrir o conteúdo das caixas de proteção remotas ou do aplicativo.
Erros na chamada de código restrito
Se você chamar um código com uso restrito em uma caixa de proteção, devido a essas restrições de segurança, o tempo de execução despachará um erro de JavaScript: "Violação de segurança de tempo de execução do Adobe AIR para código JavaScript na caixa de proteção de segurança do aplicativo."
Para obter mais informações, consulte
Como evitar erros JavaScript relacionados à segurança
.
Proteção da caixa de proteção ao carregar conteúdo HTML de uma sequência de caracteres
O método
loadString()
da classe HTMLLoader permite criar conteúdo HTML no tempo de execução. No entanto, os dados usados como conteúdo HTML podem ser corrompidos se forem carregados de uma fonte de Internet insegura. Por esse motivo, por padrão, o HTML criado com o método
loadString()
não é colocado na caixa de proteção do aplicativo e não tem acesso às APIs do AIR. Entretanto, você pode definir a propriedade
placeLoadStringContentInApplicationSandbox
de um objeto HTMLLoader como true para inserir o HTML criado usando o método
loadString()
na caixa de proteção do aplicativo. Para obter mais informações, consulte
Carregamento de conteúdo HTML de uma sequência de caracteres
.
|
|
|