Segurança com JavaScript

Da Web para o Windows 8: segurança

Tim Kulp

 

Há alguns anos, eu achei que seria uma boa ideia aprender a jogar golfe. Antes de me inscrever para ter aulas em uma área de treinamento local, eu nunca tinha ido a um clube de golfe. Em minha primeira aula, o instrutor me perguntou se eu já tinha tido aulas antes ou se já havia tentado jogar golfe. Quando eu disse a ele que nunca, ele disse: “Ótimo! Não teremos nenhum hábito antigo para eliminar de seu balanço.”.

Os desenvolvedores da Web em transição do navegador para aplicativos da Windows Store trazem certos hábitos consigo. Embora os desenvolvedores da Web consigam utilizar seu conhecimento em JavaScript existente, alguns recursos são novos e exigem uma mudança de pensamento. A segurança é uma diferença fundamental. Muitos desenvolvedores da Web têm o hábito de transferir a segurança dos aplicativos para o servidor por motivos como: “Por que se preocupar? O JavaScript pode ser facilmente ignorado.”. No lado do cliente Web, os recursos de segurança são encarados como melhorias na usabilidade sem a adição de valor à segurança geral do aplicativo Web.

No Windows 8, o JavaScript desempenha um importante papel na segurança geral de seu aplicativo, fornecendo as ferramentas necessárias para proteger dados, validar entradas e separar conteúdos potencialmente mal-intencionados. Neste artigo, mostrarei como você pode ajustar alguns dos hábitos trazidos do desenvolvimento para a Web, de forma que consiga produzir aplicativos da Windows Store mais seguros usando HTML5, JavaScript e os recursos de segurança do Tempo de Execução do Windows.

Validação de entradas

O desenvolvedor da Web diz: a validação de JavaScript destina-se à capacidade de uso e não aumenta a segurança do aplicativo.

O desenvolvedor do Windows 8 diz: a validação com HTML5 e JavaScript é a sua primeira linha de defesa contra conteúdos mal-intencionados que chegam ao seu aplicativo.

Para aplicativos Web tradicionais, o JavaScript geralmente é apenas um gateway para o servidor. Todas as ações importantes com os dados, como a validação de entradas e o armazenamento, ocorrem no servidor. Invasores mal-intencionados podem desabilitar o JavaScript em seu navegador ou diretamente enviando solicitações HTTP programadas para contornar qualquer proteção no lado do cliente. Em um aplicativo da Windows Store, o desenvolvedor não pode depender de um servidor para limpar a entrada do usuário antes de agir nos dados porque não existe nenhum servidor. Em relação à validação de entradas, o JavaScript e o HTML5 estão por conta própria.

Na segurança de software, a validação de entradas é um componente essencial para a integridade dos dados. Sem ela, os invasores podem usar todos os campos de entrada como um possível vetor de ataque no aplicativo da Windows Store. Na segunda edição de “Writing Secure Code” (Microsoft Press, 2003), os autores Michael Howard e Steve Lipner fornecem o que se tornou um mantra para o gerenciamento de entradas: “Toda entrada é perigosa até que se prove o contrário.”.

Você não deve confiar em nenhum dado até que seja comprovado que ele está de acordo com dados “válidos”. Ao compilar um aplicativo, o desenvolvedor sabe com o que os dados de um campo específico devem se parecer (ou seja, uma lista de permissões) ou, pelo menos, com o que não devem (ou seja, uma lista de negações). No mundo da validação de entradas, sempre use uma lista de permissão quando possível para restringir a entrada para dados válidos. Ao permitir apenas dados que você sabe que são válidos, você reduz a possibilidade de perder uma maneira nova ou desconhecida de representar dados inválidos.

Restringir, rejeitar e limpar

Como os desenvolvedores reduzem os riscos para seus usuários limitando a entrada a dados válidos? Eles usam os três estágios da validação de entradas mostrados na Figura 1 para reduzir os riscos de conteúdos mal-intencionados alcançarem seus aplicativos.


Figura 1 - Validação de entradas (imagem com base na Figura 4.4 do capítulo 4, “Criar diretrizes para proteger aplicativos Web” de “Aprimorando a segurança de aplicativos Web: ameaças e contramedidas” embit.ly/emYI5A)

A validação de entradas começa com a restrição dos dados para o que é “válido”. Os desenvolvedores da Web familiarizados com HTML5 podem usar seu conhecimento existente sobre seus novos tipos de entrada e novos atributos para restringir os dados que alcançam seus aplicativos da Windows Store. A principal diferença entre a Web e o Windows 8 é que um aplicativo da Windows Store não tem um servidor nos bastidores para verificar as entradas. A restrição dos dados deve ocorrer no HTML5 ou JavaScript.

Ao usar o HTML5, cada campo pode ser facilmente limitado a dados válidos. Para ilustrar os exemplos deste artigo, eu utilizarei o fictício aplicativo Contoso Health, que armazena informações médicas pessoais para usuários. A página de perfil desse aplicativo captura o nome do usuário, o endereço de email, o peso e a altura e fornece um campo de observações para informações gerais. Como desenvolvedor, eu sei (em geral) com que se assemelham os dados válidos para cada um desses campos:

  • Nome: caracteres alfabéticos com alguns caracteres especiais; não excedem 45 caracteres no total. O critério de nomenclatura baseia-se no mercado de destino do aplicativo, o mercado dos EUA.
  • Endereço de email: a entrada deve estar em um formato de endereço de email válido.
  • Peso e altura: números com rótulos associados para mostrar que os dados estão em pés e polegadas e em libras.
  • Observações: o conteúdo HTML usando o editor de HTML Contoso padrão.

Para o elemento de entrada de Nome, é necessário limitar quais são os caracteres válidos para o campo, bem como qual será a extensão do valor. É possível fazer isso usando dois atributos novos da marca de entrada: pattern e title.

Pattern é uma expressão regular com a qual os dados inseridos devem estar em conformidade. O MSHTML (mecanismo de renderização usado para aplicativos em HTML5 no Windows 8) verifica se os dados inseridos no campo correspondem à expressão regular. Se o usuário inserir dados que não estão em conformidade com o padrão da expressão regular, ocorrerá uma falha no envio do formulário e o usuário será direcionado para corrigir o campo inválido. Por exemplo, o campo Nome pode ser composto de caracteres alfabéticos e espaços, e deve conter de 3 a 45 caracteres de comprimento. O valor de pattern a seguir oferece suporte a isso:

    <input type="text" id="txtName" name="txtName"
      pattern="^[A-Za-z ]{3,45}$" title="" />

Title é usado para informar ao usuário o que o sistema está esperando. Nesse caso, algo como “O nome deve conter de 3 a 45 caracteres de comprimento e deve usar caracteres alfabéticos ou espaços” explicaria o padrão esperado. Nada é mais frustrante para os usuários do que ter uma entrada inválida sem saber qual é a entrada válida. Seja gentil com seus usuários e permita que eles saibam o que é permitido. O atributo title faz exatamente isso. Ele é a mensagem de explicação que exibe o que é esperado para o campo.

Padrões para os campos de dados, incluindo caracteres aceitáveis e comprimento, podem ser difíceis de determinar. Você pode encontrar exemplos de expressões regulares em muitos recursos online excelentes, mas sempre consulte a equipe de segurança de sua organização para verificar se existe um padrão com o qual você deve estar em conformidade. Se não houver uma equipe de segurança ou se a equipe não possuir um padrão, recursos como o site RegExLib.com fornecem uma excelente biblioteca de expressões regulares que você poderá usar em suas validações de dados.

Alguns campos são tipos de dados específicos, como números, datas e endereços de email. O HTML5 entra em ação novamente com um exército de novos tipos de entradas, como email, telefone, data, número e muito mais. Ao usar esses tipos de entrada de dados, o MSHTML verifica se os dados inseridos pelo usuário são válidos, sem a necessidade de nenhuma expressão regular nem código JavaScript. O atributo de tipo de elemento de entrada lida com os novos tipos de dados. É possível encontrar mais tipos e suas utilizações em bit.ly/OH1xFf. Por exemplo, para capturar um endereço de email para a página de perfil, eu definiria o atributo type como email, conforme exibido no exemplo a seguir:

    <input type="email" id="txtEmail" name="txtEmail" />

Esse campo aceita um valor apenas se ele estiver de acordo com o formato de um endereço de email válido. Se o MSHTML não reconhecer a entrada como um endereço de email válido, um erro de validação será exibido no campo quando o usuário tentar enviar o formulário. O uso de novos tipos de entrada do HTML5 restringe os dados para o que você está esperando, sem o incômodo da complexa validação de JavaScript.

Alguns dos novos tipos de entrada também permitem restrições de intervalos por meio dos novos atributos min e max. Como exemplo, devido às regras de negócios, as pessoas em nosso aplicativo devem ter uma altura entre 3 e 8 pés. As restrições de intervalo a seguir podem ser usadas no campo de altura:

    <input type="number" id="txtHeight" name="txtHeight" min="3" max="8" />

Os exemplos fornecidos utilizam as quatro técnicas para restringir dados com a marca de entrada de HTML5. Ao validar o comprimento (usando um padrão), o formato (novamente, usando um padrão), o tipo de dados (usando os novos tipos de entrada) e o intervalo (usando min/max), você pode restringir os dados para que sejam apenas dados válidos. Nem todos os atributos e tipos solicitam que você os corrija antes do envio. Certifique-se de validar o conteúdo de seu formulário com o método checkValidity (bit.ly/SgNgnA) da mesma maneira que faria com Page.IsValid no ASP.NET. Você deve estar se perguntando se é possível restringir dados como esses usando apenas JavaScript. Sim, é possível. E a utilização de atributos HTML5 reduz o código geral que o desenvolvedor precisa gerenciar ao transferir todo o trabalho pesado para o mecanismo MSHTML.

A rejeição nega as entradas inválidas (ou seja, uma lista de negações). Um bom exemplo de rejeição é a criação de uma lista de negações de endereços IP que não podem se conectar ao seu aplicativo Web. As listas de negações são úteis quando você tem um escopo de alguma maneira fixo definido para o que você deseja bloquear. Como exemplo, considere o envio de um email a um grupo, como a sua equipe de desenvolvimento, e, em seguida, a remoção específica de indivíduos da lista de emails da equipe de desenvolvimento. Nesse exemplo, você sabe quais são os endereços de email que deseja negar na lista da equipe de desenvolvimento. Para proteger o software, você deseja se concentrar em restrições (uma lista de permissões), em vez de rejeições (uma lista de negações). Lembre-se sempre de que os dados inválidos mudam constantemente à medida que os invasores encontram maneiras cada vez mais criativas de contornar as defesas do software. No exemplo anterior, imagine novos desenvolvedores se unindo à equipe de desenvolvimento e a necessidade de verificar se eles devem ser incluídos no email. As restrições são muito mais fáceis de gerenciar a longo prazo, além de fornecerem uma lista mais fácil de manter em oposição aos milhares de itens em uma de negações.

Às vezes, os dados podem conter dados válidos e inválidos. Um exemplo disso é o conteúdo HTML. Algumas marcas são aprovadas para exibição, ao passo que outras não são. O processo de filtrar ou desabilitar os dados inválidos e permitir os dados aprovados é conhecido como limpeza de entradas. O campo de observações no aplicativo Contoso Health é um excelente exemplo disso. Os usuários podem inserir marcas HTML por meio de um editor de HTML, mas apenas determinadas marcas HTML são renderizadas quando a entrada é exibida no aplicativo. A limpeza de entradas contém os dados que podem ser mal-intencionados e os torna seguros removendo o conteúdo que não é seguro e renderizando de maneira inerte o que não está explicitamente aprovado. Os aplicativos da Windows Store podem fazer isso se você definir o valor de um elemento HTML usando innerText (em vez de innerHTML), que renderiza o conteúdo HTML como texto, em vez de interpretá-lo como HTML. Observe que, se o aplicativo definir o innerText de uma marca de script como JavaScript, um script executável será gerado. O JavaScript também fornece outra ferramenta útil para a limpeza: o toStaticHTML.

Este é um código de exemplo do manipulador btnSave_Click da página de perfil:

function btnSave_Click(args) {
  var taintedNotes = document.getElementById("txtNotes").value;
  var sanitizedNotes = window.toStaticHTML(taintedNotes);
  document.getElementById("output").innerHTML = sanitizedNotes;
}

Se o usuário inserir a cadeia de caracteres

    <strong>testing!</strong><script>alert("123! ");</script>

ao txtNotes, o método window.toStaticHTML removerá a marca de script e deixará apenas a marca strong aprovada. Ao usar toStaticHTML, todas as marcas que não estiverem na lista de confiança aprovada serão removidas (outro exemplo de uso de uma lista de permissões), bem como todos os atributos desconhecidos. Apenas dados válidos são mantidos no resultado do método toStaticHTML. Você pode verificar uma listagem completa de marcas aprovadas, atributos, regras de CSS e propriedades em bit.ly/KNnjpF.

A validação de entradas reduz o risco de entrada de conteúdo mal-intencionado no sistema. Ao usar HTML5 e toStaticHTML, o aplicativo pode restringir a entrada a dados válidos e remover ou desabilitar conteúdos possivelmente mal-intencionados sem a intervenção do servidor.

Agora que o Contoso Health está obtendo dados válidos, o que devemos fazer com os dados confidenciais, como informações médicas ou financeiras?

Armazenamento de dados confidenciais

O desenvolvedor da Web diz: nunca armazene dados confidenciais no cliente, pois o armazenamento seguro não está disponível.

O desenvolvedor do Windows 8 diz: os dados confidenciais podem ser criptografados e armazenados com segurança por meio do Tempo de Execução do Windows.

Na seção anterior, o aplicativo Contoso Health recuperou informações gerais de perfil. À medida que o desenvolvimento continua, um formulário de histórico médico é solicitado pelo responsável pelo negócio. Esse formulário captura eventos médicos que ocorreram por toda a vida do usuário, como a mais recente visita ao médico. Regras antigas para o desenvolvimento para a Web afirmam que o armazenamento de informações confidenciais, como o histórico médico de um usuário, no cliente não é uma boa ideia devido à possível exposição dos dados. No desenvolvimento de aplicativos da Windows Store, os dados confidenciais podem ser armazenados localmente usando os recursos de segurança do Tempo de Execução do Windows.

Para proteger o histórico médico do usuário, o Contoso Health utiliza a API de Proteção de Dados do WinRT. A criptografia não deve ser a única parte de sua estratégia de proteção de dados (pense em defesa profunda: camadas de segurança, em vez de uma única defesa, como o uso apenas de criptografia). Não se esqueça de outras práticas recomendadas relacionadas a dados confidenciais, como o acesso a dados apenas quando necessário e a manutenção de dados confidenciais fora do cache. Um excelente recurso que lista várias considerações sobre dados confidenciais é o artigo “Aumentando a segurança do aplicativo Web: ameaças e contramedidas” na Biblioteca MSDN (bit.ly/NuUe6w). Embora esse documento esteja concentrado em práticas recomendadas de desenvolvimento para a Web, ele fornece um abrangente conhecimento de base excelente que você pode aplicar a qualquer tipo de desenvolvimento.

A página de histórico médico no aplicativo Contoso Health possui um botão chamado btnAddItem. Quando o usuário clica em btnAddItem, o aplicativo criptografa os dados inseridos no formulário de histórico médico. Para criptografar as informações do histórico médico, o aplicativo utiliza a API interna de Proteção de Dados do WinRT. Esse sistema de criptografia simples permite que os desenvolvedores criptografem dados rapidamente, sem a sobrecarga do gerenciamento de chaves. Comece com um manipulador de eventos vazio para o evento de clique btnAddItem. Em seguida, o Contoso Health coletará as informações do formulário e as armazenará em um objeto JSON. No manipulador de eventos, eu adiciono o código para compilar rapidamente o objeto JSON:

var healthItem = {
  "prop1": window.toStaticHTML(document.getElementById("txt1").value),
  "prop2": window.toStaticHTML(document.getElementById("txt2").value)
};

O objeto healthItem representa o registro do histórico médico que o usuário inseriu no formulário. A criptografia de healthItem começa com a criação de instância de um DataProtectionProvider:

var dataProtectionProvider =
  Windows.Security.Cryptography.DataProtection.DataProtectionProvider(
  "LOCAL=user");

O construtor DataProtectionProvider (para criptografia) obtém um argumento de cadeia de caracteres que determina a que a Proteção de Dados está associada. Nesse caso, estou criptografando conteúdo para o usuário local. Em vez de configurá-lo para o usuário local, eu poderia configurá-lo para o computador, um conjunto de credenciais da Web, um princípio de segurança do Active Directory ou algumas outras opções. Você pode encontrar uma lista de opções de descrição de proteção no Centro de Desenvolvimento, no tópico “Descritores de proteção” (bit.ly/QONGdG). O descritor de proteção usado depende dos requisitos de seu aplicativo. Nesse ponto, o Provedor de Proteção de Dados está pronto para criptografar os dados, mas os dados necessitam de uma pequena alteração. Os algoritmos de criptografia funcionam com buffers, e não com JSON. Por isso, a próxima etapa é definir healthItem como um buffer:

var buffer =
  Windows.Security.Cryptography.CryptographicBuffer.convertStringToBinary(
    JSON.stringify(healthItem),
    Windows.Security.Cryptography.BinaryStringEncoding.utf8);

CryptographicBuffer possui muitos objetos e métodos para trabalhar com os buffers usados na criptografia e descriptografia. O primeiro desses métodos é convertStringToBinary, que obtém uma cadeia de caracteres (nesse caso, a versão de cadeia de caracteres do objeto JSON) e a converte em um buffer codificado. A codificação utilizada é definida com o objeto Windows.Security.Cryptography.Binary­StringEncoding. Nesse exemplo, eu usei UTF8 como a codificação para os meus dados. O método convertStringToBinary retorna um buffer com base nos dados de cadeia de caracteres e na codificação especificados. Com o buffer pronto para ser criptografado e o Provedor de Proteção de Dados instanciado, eu estou pronto para chamar o método protectAsync para criptografar o buffer:

dataProtectionProvider.protectAsync(buffer).then(
  function (encryptedBuffer) {
     SaveBufferToFile(encryptedBuffer);
});

O argumento encryptedBuffer é a saída do método protectAsync e contém a versão criptografada do buffer. Em outras palavras, esse é o dado criptografado pronto para o armazenamento. A partir daqui, encryptedBuffer é transmitido para o método SaveBufferToFile, que grava os dados criptografados em um arquivo na pasta local do aplicativo.

A criptografia de healthItem se resume a três linhas de código:

  1. Instanciar o Provedor de Proteção de Dados.
  2. Converter os dados em um buffer.
  3. Chamar protectAsync para criptografar os dados.

A descriptografia dos dados também é muito simples. As únicas mudanças são a utilização de um construtor vazio para DataProtectionProvider e a utilização do método unprotectAsync, em vez do método protectAsync. O método GetBufferFromFile carrega a variável encryptedBuffer a partir do arquivo criado no método SaveBufferToFile:

function btnLoadItem_Click(args) {
  var dataProtectionProvider =
    Windows.Security.Cryptography.DataProtection.DataProtectionProvider();
  var encryptedBuffer = GetBufferFromFile();
  dataProtectionProvider.unprotectAsync(encryptedBuffer).then(
    function (decryptedBuffer) {
      // TODO: Work with decrypted data
    });
}

Os desenvolvedores podem usar a criptografia com JavaScript que não seja de WinRT ? Sim! É tão fácil quanto as três linhas de código que fornecem uma excelente proteção de dados? Não. Existem diversos desafios para as melhores práticas de criptografia no navegador, como manter a chave secreta como um segredo, além de gerenciar o tamanho do arquivo dos algoritmos necessários para a obtenção de uma criptografia de qualidade. A API de Proteção de Dados do WinRT, bem como as outras ferramentas de criptografia fornecidas no namespace Windows.Security.Cryptography, simplificam a proteção de seus dados. Ao usar os recursos de segurança do Tempo de Execução do Windows, os desenvolvedores podem armazenar dados confidenciais em seus aplicativos da Windows Store com confiança e, ao mesmo tempo, manter suas chaves criptográficas fáceis de gerenciar.

Contexto local versus Web

O desenvolvedor da Web diz: os aplicativos Web executam referências de script externas na mesma origem do aplicativo que chama os scripts.

O desenvolvedor do Windows 8 diz: os aplicativos da Windows Store separam o pacote de aplicativos local das referências de script externas.

A Web 2.0 ensinou aos desenvolvedores que o conteúdo pode vir de seu site, do site de outra pessoa (via mashup) ou da interação do usuário. Na Web, o conteúdo é uma desordem virtual, com desenvolvedores consumindo referências script e dados de API de terceiros. As CDNs (Redes de Fornecimento de Conteúdo) e os serviços online, como o Bing Maps, eliminam a sobrecarga de gerenciar bibliotecas de códigos ou grandes repositórios de dados, o que permite que os aplicativos Web facilmente se ajustem em relação à funcionalidade. Menos sobrecarga é bom, mas esse benefício vem acompanhado de alguns riscos.

Como exemplo, imagine que um dos parceiros da Contoso no setor de software para a área de saúde seja a Litware Inc. A Litware está lançando uma nova API de Exercícios e forneceu aos desenvolvedores da Contoso Health chaves para consumir um feed de dados de exercícios diário. Se o Contoso Health fosse um aplicativo Web, a equipe de desenvolvimento poderia implementar a API de Exercícios usando uma referência de script como a seguinte:

    <script src="https://api.litware.com/devkey/exercise.js"></script>

Os desenvolvedores da Contoso confiam na Litware para o fornecimento de excelente conteúdo e sabem que ela possui ótimas práticas de segurança. Infelizmente, os servidores da Litware foram comprometidos por um desenvolvedor insatisfeito e exercise.js foi alterado para ter um script de inicialização que exibe um pop-up com a mensagem “O Contoso Health precisa realizar a manutenção; baixe o seguinte aplicativo de manutenção.”. O usuário, acreditando que a mensagem era legítima, foi induzido a baixar um malware. Os desenvolvedores da Contoso ficaram desnorteados — a Litware usa uma excelente validação. Como essa violação pode ter acontecido?

Na Web, os scripts referenciados da maneira recém-descrita são executados com a mesma origem que um script no mesmo site. Isso significa que exercise.js (em execução como JavaScript) possui acesso inquestionável à arvore DOM, bem como a qualquer objeto de script. Conforme ilustrado anteriormente, isso pode levar a sérios problemas de segurança. Para reduzir esse risco, o Windows 8 separa os recursos do aplicativo em dois contextos, conforme ilustrado na Figura 2.


Figura 2 - Recursos de contexto local versus Web (combinação de “Recursos e restrições por contexto”, embit.ly/NZUyWt, e “Desenvolvimento seguro com HTML5”, embit.ly/JOoMOS)

O contexto local pode acessar o Tempo de Execução do Windows, bem como qualquer recurso incluído no pacote do aplicativo (como HTML, script, CSS e dados do aplicativo armazenados nos diretórios de estado do aplicativo), mas não pode acessar HTML, JavaScript ou CSS remoto (conforme o exemplo de exercise.js anterior). O aplicativo de nível superior no Windows 8 sempre é executado no contexto local. Na Figura 2, ms-appx:// é usado para resolver o conteúdo no contexto local. Esse esquema é usado para fazer referência ao conteúdo no pacote do aplicativo em execução no contexto local. Com frequência, há uma terceira barra (ms-appx:///) para fazer referência ao nome completo do pacote. Para os desenvolvedores da Web, essa abordagem é semelhante ao uso de arquivo:// protocolo, em que uma terceira barra faz referência ao sistema de arquivos local (pressuponha que arquivo://COMPUTADOR DO USUÁRIO FINAL/, em vez de arquivo://COMPUTADOR REMOTO/).

O contexto Web permite que os desenvolvedores levem conteúdo remoto para seus aplicativos da Windows Store por meio de um iframe. Da mesma maneira que os iframes em um navegador da Web, o conteúdo em execução no iframe não pode acessar recursos fora dele, como o Tempo de Execução do Windows e alguns recursos da Biblioteca do Windows para JavaScript. É possível encontrar uma listagem completa em bit.ly/PoQVOj. A finalidade do contexto Web é permitir que os desenvolvedores façam referência a APIs de terceiros, como o Bing Maps, ou obter uma biblioteca de um CDN para seus aplicativos.

Utilizar http:// ou https:// como a origem de um iframe automaticamente converte o conteúdo do iframe para o contexto Web. Um iframe também pode ser um recurso no pacote do aplicativo quando você estiver usando ms-appx ou ms-appx-web. Quando a origem de um iframe faz referência ao esquema ms-appx://, o conteúdo do iframe é executado no contexto local. Isso permite que os desenvolvedores insiram recursos do pacote do aplicativo em um iframe e ainda tenham acesso aos recursos do contexto local (como o Tempo de Execução do Windows, a API de JavaScript do Windows, entre outros). Outro esquema disponível é o ms-appx-web://, que permite que o conteúdo do pacote do aplicativo local seja executado no contexto Web. Esse esquema é útil quando você precisa inserir conteúdo remoto em sua marcação, como a adição do resultado de uma pesquisa do Bing (a partir da API de Pesquisa do Bing) de hospitais locais com base no local do usuário no aplicativo Contoso Health. Como uma observação rápida, sempre que os iframes forem mencionados com o HTML5, lembre-se de que você pode usar o atributo sandbox como uma proteção extra para o seu aplicativo, limitando a execução de script do conteúdo dentro do iframe. Você pode obter mais informações sobre o atributo sandbox em bit.ly/Ppbo1a.

A Figura 3 mostra os vários esquemas usados nos contextos local e Web juntamente com exemplos de sua utilização.

Figura 3 - Exemplos de esquemas com contexto

Esquema Local do conteúdo Contexto Exemplo Utilização
ms-appx:// Pacote do aplicativo Local

<iframe

 src="ms-appx:///1.html"

></iframe>

Carregar conteúdo em um iframe que precisa acessar o Tempo de Execução do Windows ou toda a API de JavaScript do Windows.
ms-appx-web:// Pacote do aplicativo Web

<iframe

 src="ms-appx-web:///2.html"

></iframe>

Usar conteúdo de uma origem remota como parte da interface de seu aplicativo da Windows Store, por exemplo, exibir um widget de mapeamento ou resultados de pesquisa.
http:// Remoto Web

<iframe

 src="http://host/3.html"

></iframe>

Fazer referência ao conteúdo remoto, como uma página da Web ou um arquivo de script em outro servidor.

A que contexto um iframe pertence baseia-se em como o conteúdo dentro dele é referenciado. Ou seja, o esquema determina o contexto. Você pode obter mais informações sobre os esquemas usados no Windows 8 em bit.ly/SS711o.

Você se lembra do cenário de invasão da Litware no início desta seção? A separação de contextos do Windows 8 ajudará a restringir o ataque de scripts entre sites para o contexto Web, no qual ele não tem acesso ao Tempo de Execução do Windows nem aos dados do aplicativo para o Contoso Health. No contexto Web, a modificação do contexto local não é uma opção. A comunicação entre os contextos é possível, mas você tem o controle sobre o tipo de comunicação que ocorre.

Comunicação entre contextos

Como o documento de nível superior se comunica com um iframe em execução no contexto Web? Usando os recursos de postMessage do HTML5, os aplicativos da Windows Store podem transmitir dados entre contextos. Isso possibilita que os desenvolvedores estruturem como as duas origens se comunicam e permitam apenas provedores válidos (novamente, a lista de permissões) por meio do contexto local. As páginas que precisam ser executadas no contexto Web são referenciadas usando um iframe com o atributo src definido como http://, https:// ou ms-appx-web://.

Para o aplicativo Contoso Health, o sistema obtém dicas de ginástica da API de Exercícios da Litware. A equipe de desenvolvimento do Contoso Health criou a página litwareHelper.html, que é usada para a comunicação com a API de Exercícios por meio do objeto jQuery $ajax. Devido ao recurso remoto (exercise.js), a página litwareHelper.html deve ser executada no contexto Web, o que significa que ela deve ser executada em um iframe. A configuração do iframe não é diferente de qualquer outro aplicativo Web, exceto pela maneira como a página é referenciada. Como a página litwareHelper.html faz parte do pacote do aplicativo local, mas precisa ser executada no contexto Web, você deve carregá-la usando ms-appx-web:

    <iframe id="litwareHelperFrame” src="ms-appx-web:///litwareHelper.html"></iframe>

A equipe de desenvolvimento adiciona a seguinte função à página de contexto local que envia a solicitação de dados à página de contexto Web:

function btnGetFitTips_Click() {
  var msg = {
    term: document.getElementById("txtExerciseSearchTerm").value,
    itemCount: 25  }
  var msgData = JSON.stringify(msg);
  var domain = "ms-appx-web://" + document.location.host;
  try {
    var iframe = document.getElementById("litwareHelperFrame");
    iframe.contentWindow.postMessage(msgData, domain);
  }
  catch (ex) {
    document.getElementById("output").innerText = "Error has occurred!";
  }
}

O método receiveMsg processa a mensagem do contexto local. O argumento de receiveMsg são os dados fornecidos ao evento postMessage (nesse caso, a variável msgData) juntamente com o destino da mensagem, a origem da mensagem e algumas outras pequenas informações, conforme exibido na Figura 4.

Figura 4 - Processando com receiveMsg

function receiveMsg(e) {
  if (e.origin === "ms-appx://" + document.location.host) {
    var output = null;
    var parameters = JSON.parse(e.data);
    var url = "https://api.litware-exercise.com/data/" 
      + parameters.term +
      "/count/" + parameters.itemCount;
    var options = {
      dataType: "jsonp",
      jsonpCallback: "jsonpCallback",
      success: function (results) {
        output = JSON.stringify(results.items);
        window.parent.postMessage(output, "ms-appx://" 
        + document.location.host);
      },
      error: function (ex) {
        output = ex;
      }
    };
    $.ajax(url, options);
  }
}

A primeira etapa de receiveMsg verifica a origem de postMessage. Essa é uma verificação de segurança essencial para garantir que a mensagem seja proveniente de onde supõe-se que ela foi originada. Lembre-se de que e.origin verifica o domínio e o esquema de quem enviou o postMessage, que é o motivo pelo qual você está verificando o ms-appx (o endereço de contexto local). Depois de reunir os dados de JSON a partir da API da Litware, o aplicativo transmite o resultado de volta para window.parent usando um comando postMessage. Observe em receiveMsg que o domínio está definido como ms-appx. Esse é o endereço “para” de destino da mensagem e mostra que os dados estão retornando para o contexto local. Os dados do iframe devem ser consumidos por recursos no contexto local. A equipe de desenvolvimento adiciona a função processResult para consumir os dados do contexto Web de volta para o contexto local:

function processResult(e) {
  if (e.origin === "ms-appx-web://" + document.location.host) {
    document.getElementById("output").innerText = e.data;
  }
}

Novamente, sempre verifique a origem do evento de mensagem para garantir que apenas os dados de locais aprovados (ou seja, locais registrados na lista de permissões) sejam processados. Observe que a origem é o esquema do contexto Web: ms-appx-web no método processResult. A alternância entre os esquemas pode ser um problema que os desenvolvedores talvez não percebam e se perguntem para onde suas mensagens foram durante a depuração.

Por fim, para receber dados do contexto Web de volta à página de contexto local, você deve adicionar um manipulador de eventos para o evento de mensagem. No método app.onactivated, adicione o ouvinte de eventos ao objeto window:

window.addEventListener('message', processResult, false);

A separação dos contextos local e Web, por padrão, reduz o risco de execução acidental de códigos de uma fonte externa ao aplicativo da Windows Store. Ao usar o postMessage, os desenvolvedores podem fornecer um canal de comunicação entre o script externo e os scripts locais que compõem um aplicativo.

Da Web para o Windows 8: novas ferramentas para hábitos antigos

Os desenvolvedores da Web agora têm acesso a ferramentas familiares e a novas ferramentas que eles podem usar para compilar aplicativos seguros da Windows Store. A utilização de habilidades existentes, como a validação de entradas de HTML5, assegura a integridade dos dados recebidos pelo aplicativo. Novas ferramentas, como a API de Proteção de Dados (nova para o Tempo de Execução do Windows), protegem os dados confidenciais dos usuários com uma criptografia robusta que é simples de implementar. A utilização de postMessage permite que os aplicativos utilizem as milhares de bibliotecas JavaScript e os milhares de códigos herdados na Web e, ao mesmo tempo, mantenham os usuários protegidos contra injeções de código não intencionais. Todos esses elementos funcionam juntos para fornecer algo importante que, frequentemente, é desprezado no JavaScript: segurança.

O Windows 8 fornece aos desenvolvedores da Web a chance de repensar alguns de seus antigos hábitos. O JavaScript não é mais uma fachada para o servidor, desprezado como um aprimoramento para a capacidade de uso e nada mais. O JavaScript, o Tempo de Execução do Windows e o MSHTML fornecem as ferramentas necessárias para compilar recursos de segurança em seus aplicativos da Windows Store — sem necessidade de servidor. Como desenvolvedores da Web, nós temos um amplo conjunto de habilidades para aproveitar, mas precisamos manter um pouco de atenção em nossos antigos hábitos e transformá-los em oportunidades para aprender o novo mundo do Windows 8.

Tim Kulp lidera a equipe de desenvolvimento da FrontierMEDEX em Baltimore, Md. Você pode encontrar Kulp em seu blog, em seccode.blogspot.com, ou pode segui-lo no Twitter, em Twitter.com/seccode, onde ele fala sobre códigos, segurança e o cenário gastronômico de Baltimore.

Agradecemos ao seguinte especialista técnico pela revisão deste artigo: Scott Graham