Desenvolvendo aplicativos seguros

Os aplicativos da Windows Store em JavaScript permitem aos desenvolvedores combinar a versatilidade e expressividade das tecnologias da Web com uma grande variedade de APIs avançadas disponíveis no Tempo de execução do Windows. Esses aplicativos têm todo o poder dos aplicativos nativos convencionais e precisam ser igualmente seguros. Felizmente, a plataforma foi projetada tendo a segurança em mente e inclui várias "grades de proteção" de segurança que, quando combinadas com as melhores práticas, facilitam a criação de um aplicativo seguro.

Fontes comuns de dados

Os aplicativos da Windows Store têm acesso ao grande número de fontes de dados que hoje existe na Web. Cada uma dessas fontes de dados requer a manipulação segura pelos desenvolvedores e deve sempre ser validada para assegurar que os scripts mal-intencionados ou outro tipo de conteúdo perigoso não comprometam o aplicativo.

Você até mesmo precisa verificar e remover códigos mal-intencionados nos dados provenientes de uma fonte confiável, como um serviço Web de back-end. Os dados podem ser modificados em trânsito ou o próprio serviço de back-end pode ter sido comprometido. Para garantir a segurança do aplicativo e proteger os seus usuários, verifique todos os dados que o aplicativo recebe da rede.

A primeira etapa para garantir a segurança é identificar os pontos onde os dados fluem para a aplicativo. Aqui estão algumas fontes comuns de dados que podem potencialmente comprometer o seu aplicativo:

Esses são apenas alguns exemplos de fontes de dados não confiáveis. A primeira etapa para assegurar o seu aplicativo é fazer um inventário dos dados originados a partir da rede.

Contextos de segurança e filtragem de scripts

A infraestrutura dos aplicativos da Windows Store que usam JavaScript foi desenvolvida para ajudar os desenvolvedores a evitar problemas de segurança comuns que podem resultar do manuseio inseguro de dados não confiáveis. Um novo recurso que pode ajudar a melhorar a segurança é o suporte para os contextos locais e da Web. Esses contextos aos desenvolvedores criar seus aplicativos a partir do zero para segregar conteúdo não confiável, como JavaScript remoto, a partir do código confiável e dos dados incluídos no pacote do aplicativo.

O isolamento de quadros padrão separa os contextos da Web e local, e seus contextos são determinados automaticamente com base na origem do conteúdo. Por exemplo, o conteúdo referido via protocolo ms-appx:// é automaticamente carregado em um quadro de contexto local, enquanto o conteúdo remoto da Web carregado por um iframe é sempre carregado no contexto da Web. Os dois contextos têm propriedades de segurança e níveis de acesso diferentes (descritos em Recursos e restrições por contexto). Embora os dois contextos tenham níveis diferentes de acesso, a comunicação entre quadros conveniente está disponível usando a infraestrutura postMessage.

O script automático de filtragem dos métodos do DOM remove qualquer conteúdo dinâmico que for considerado inseguro e impede que ele seja injetado no DOM, permitindo que a marcação benigna permaneça intacta. Se a finalidade do conteúdo é ser adicionado a um elemento existente do DOM, é seguro usar as propriedades innerText ou outerText para adicionar o conteúdo.

Aviso de segurança:  Observe que o script de filtragem automática não é aplicado quando você usa innerText e outerText para definir o texto de um elemento script.

Embora a filtragem automática de scripts seja uma ótima "grade de proteção" que pode evitar que ataques inesperados à segurança prejudiquem o usuário, não permita que ela seja a única defesa do seu aplicativo. Quando a filtragem automática de scripts bloqueia conteúdo, aciona um erro que pode afetar a experiência do usuário. Além disso, as bibliotecas de terceiros que funcionam com dados pode usar APIs que não são automaticamente filtradas, que pode causar problemas de segurança. É uma melhor prática evitar depender da filtragem automática de scripts como uma defesa universal e, em vez disso executar a filtragem proativa dentro do seu código. A execução da filtragem explícita de dados não confiáveis é a melhor maneira de assegurar que o seu aplicativo permaneça seguro.

Validar a origem dos dados invokeScriptAsync e postMessage

Os controles WebView (XAML) e x-ms-webview (HTML) possuem métodos semelhantes ao método postMessage para um iframe que permite a comunicação entre contextos. Os métodos InvokeScriptAsync (XAML) e invokeScriptAsync (HTML) são a principal maneira de transferir dados entre os contextos locais e da Web em um aplicativo da Windows Store.

O método postMessage é a principal maneira de transferir dados entre os contextos locais e da Web em um aplicativo da Windows Store que usa JavaScript. Em vez de usar o elemento de script ou violação entre domínios para criar aplicativos mashup (aplicativos que combinam dados de diferentes fontes na Web), use postMessage. A utilização de separação baseada em quadros entre fontes locais e remotas permite aos desenvolvedores incluir conteúdo remoto, como mapas ou anúncios, mantendo o acesso a documentos e recursos isolado por meio do uso da política de mesma origem.

Para usar métodos postMessage e invokeScriptAsync com segurança para transmitir mensagens entre documentos locais e remotos, verifique a origem de uma resposta do postMessage ou invokeScriptAsync antes de usar os dados. Isso é necessário porque muitos aplicativos incluem vários elementos iframe ou WebView remotos, cada um com uma origem e nível de confiança diferente. Normalmente, um aplicativo usa uma função de manipulador onmessage individual para cada página que trata mensagens de todos os elementos iframe ou WebView da página.

Este exemplo mostra como chamar o método invokeScriptAsync (HTML).


// The application is calling for a specific function inside of the webview
var asyncOp = webView.invokeScriptAsync(“startAnimation”, “500”);
    
asyncOp.oncomplete = function(e){
	// Even though the risk is less with the invokeScript message
	// still make sure not to use eval on the return value.
}

asyncOp.start();



Este exemplo mostra como chamar o método InvokeScriptAsync (XAML).


async void webview_DOMContentLoaded(WebView sender, WebViewDOMContentLoadedEventArgs args)
{
    var operation = await webview.InvokeScriptAsync("startAnimation", new string[] { "500" });

    if (operation == "success")
    {
        // Handle the message.
    }
} 


Para melhorar a segurança dos controles WebView, restringimos quando a função window.external.notify() pode ser usada a partir do conteúdo de WebView. Essas restrições impedem que um conteúdo não confiável ou adulterado envie mensagens executadas sem validação para o host. Para que o conteúdo seja capaz de enviar notificações, uma das seguintes condições deve ser verdadeira:

  • A origem da página é do sistema local via NavigateToString, NavigateToStream ou ms-appx-web:///.
  • A origem da página é entregue via https://, e o nome de domínio do site está listado na seção URLs de Conteúdo do manifesto do pacote de aplicativo.
Por exemplo:

webview.addEventListener("MSWebViewScriptNotify", handleScriptNotifyEvents);
function handleScriptNotifyEvents(e) {
        if (e.callingUri === "https://msgnotify.example.net/") {
            if(e.value === "msg1")
            {
                // Process the message.);
            }
        }
    }


Esse exemplo mostra duas versões de um manipulador onmessage: o primeiro não é seguro e o segundo é seguro.


// This message handler is not secure because it does not implement an origin check
window.addEventListener('message', function (e) { 
    div.innerHTML = window.toStaticHTML(e.data); 
}, false);

// Secure message handler, validates message domain origin 
window.addEventListener('message', function (e) {
    if (e.origin === 'http://data.contoso.com') { 
        div.innerHTML = window.toStaticHTML(e.data); 
    }
}, false);


Na maioria dos casos, um aplicativo quer aceitar mensagens de um ou dois elementos iframe que enviam coordenadas de mapa ou outro conteúdo mashup legítimo, enquanto rejeita outros tipos de conteúdo de mensagem de entidades não confiáveis, como anúncios ou transmissões de comentários. A filtragem de mensagens por origem é uma ótima maneira de reduzir a superfície de ataque de um aplicativo e de assegurar que os dados não confiáveis sejam rejeitados. Certifique-se de verificar a origem dos seus dados sempre que você manipular o evento onmessage.

Filtragem automática de scripts

Sempre execute filtragem de scripts e validação em fontes de dados não confiáveis. Como validar os dados dependerá da finalidade dos dados. Para adicionar dados simples e estáticos ao DOM, use APIs do DOM que ignorem elementos dinâmicos. Essa abordagem permite que você exiba o conteúdo de forma segura, pois todos os scripts ou elementos dinâmicos nos dados são exibidos como texto simples, em vez de serem interpretados como código. Você pode usar métodos como createTextNode para preencher um elemento com os dados não confiáveis, que podem então ser adicionados ao DOM do documento chamando appendChild ou importNode. Se a finalidade do conteúdo é ser adicionado a um elemento existente do DOM, é seguro usar as propriedades innerText ou outerText para adicionar o conteúdo.

Este exemplo adiciona conteúdo dinâmico de uma forma que não é segura.



// Do not use this code.
// Avoid adding untrusted dynamic content
// Unsafe method 1
var myDiv = document.createElement("div");
myDiv.innerHTML = xhr.responseText 
document.body.appendChild(myDiv);

// Unsafe method 2
document.writeln(xhr.responseText);


O próximo exemplo mostra a maneira segura de adicionar o conteúdo:



// Forcing untrusted content into static text is safe

// method 1
var myDiv = document.createElement("div");
myDiv.innerText = xhr.responseText 
document.body.appendChild(myDiv);

// method 2
var myData = document.createTextNode(xhr.responseText);
document.body.appendChild(myData);

// method3
var oDiv = document.getElementById("div1");
oDiv.outerText = xhr.responseText;



Quando os dados não confiável contém marcações, use o método window.toStaticHTML do DOM para remover a marcação insegura, mantendo os dados seguros intactos.


// The untrusted data contains unsafe dynamic content
var unTrustedData = "<img src='http://www.contoso.com/logo.jpg' on-click='calltoUnsafeCode();'/>";

// Safe dynamic content can be added to the DOM without introducing errors
var safeData = window.toStaticHTML(unTrustedData);

// The content of the data is now 
// "<img src='http://www.contoso.com/logo.jpg'/>" 
// and is safe to add because it was filtered
document.write(safeData);



Ignorando a filtragem automática de scripts

As APIs do DOM que permitem injetar marcação dinâmica são filtradas automaticamente, mas as entradas de execução explícitas, como eval, não são. Você pode usar eval para ignorar a filtragem automática e executar o script dinâmico que você sabe ser seguro. Aqui está uma lista de métodos de execução de scripts que o sistema não filtra automaticamente quanto a conteúdo não seguro:

Como o sistema não fornece filtragem automática para esses métodos, não os use para executar dados não confiáveis sem filtragem ou codificação.

A API MSApp.execUnsafeLocalFunction permite que uma função ignore a filtragem automática de scripts que é normalmente aplicada ao conteúdo da marcação dinâmica no contexto local. Isso é útil quando você quiser usar uma biblioteca de modelos de geração de marcação, como a JQuery, que poderiam ser impedidas pela filtragem automática.

Como é o caso quando se usa o método eval, a utilização de MSApp.execUnsafeLocalFunction para processar fontes não confiáveis dados pode levar a problemas de segurança. Os problemas de segurança são possíveis porque as bibliotecas de modelos podem gravar internamente os dados não confiáveis no documento. Em caso de dúvida sobre a origem de algum dado, use uma biblioteca de codificação segura ou o método toStaticHTML para assegurar que os dados estejam livres de elementos e códigos não seguros.

Usando analisadores seguros

O uso do método eval do JavaScript para gerar um objeto JavaScript local de uma resposta JSON (JavaScript Object Notation) de um servidor é uma prática comum, mas perigosa, de desenvolvimento da Web. Este exemplo usa o método eval para processar dados JSON:


<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div id="foo"></div>
    <script type="text/javascript">
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "http://contoso.com/json.js", false);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if (xhr.status == 200) {

			                 // DO NOT USE, UNSAFE
                    var myObject = eval('(' + xhr.responseTxt + ')');
                }
            }
        };
        xhr.send();
     </script>
</body>
</html>


Um problema de segurança pode ocorrer se um invasor usar escutas ativas para adulterar os dados que você passa para o método eval. Em vez de usar eval, use o método de JSON.parse do DOM para converter o texto JSON em um objeto. O método JSON.parse rejeita qualquer script que não seja JSON que possa introduzir um ataque.

O próximo exemplo usa o método JSON.parse em vez de eval.


<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div id="foo"></div>
    <script type="text/javascript">
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "http://remote-server.com/json.js", false);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if (xhr.status == 200) {
                    var myObject = JSON.parse(xhr.responseText);
                }
            }
        };
        xhr.send();
     </script>
</body>
</html>
</body>
</html>



Proteger os dados confidenciais

Certifique-se de que o seu aplicativo trata dados confidenciais de forma adequada. Para manter a custódia segura dos dados do usuário, use SSL sempre que dados confidenciais forem retornados e enviados para servidores remotos. As ferramentas de ataque à segurança estão amplamente disponíveis. Suponha que as partes com intenção maliciosa inevitavelmente procurem atacar qualquer aplicativo que não esteja usando SSL para que possam interceptar dados privados.

Além de proteção da privacidade, o protocolo SSL oferece benefícios para a integridade dos aplicativos. O SSL impede adulterações por invasores com JSON ou outras transmissões de dados da rede. É fundamental proteger a integridade do tráfego quando você envia dados da rede para as APIs do Tempo de execução do Windows, porque essas APIs podem acessar o sistema do usuário.

Exigir conexões HTTPS

É fácil forçar todo o conteúdo remoto a ser transmitido e recebido através de HTTPS (Secure Hypertext Transfer Protocol). Basta adicionar uma marca HTML meta simples à página inicial, desta forma:


<meta name="ms-https-connections-only" content="true"/>

A adição dessa marca meta faz com que qualquer navegação que não seja HTTPS emita um erro e proteja o usuário de adulteração na conexão, como envenenamento do cache do DNS (Domain Name System) ou falsificação do cache ARP (Address Resolution Protocol).

Os aplicativos da Windows Store que usam JavaScript oferecem suporte a agrupamento de certificados privados com o pacote de aplicativos para os desenvolvedores que não têm uma infraestrutura PKI existente.

Usando a XDomainRequest

Diferentemente dos navegadores convencionais, o script e a marcação locais nos aplicativos da Windows Store em JavaScript têm acesso irrestrito entre domínios aos serviços Web quando usam XMLHttpRequest. Por padrão, a XMLHttpRequest faz solicitações autenticadas por cookies para um determinado site, quando interage com um serviço Web ou obtém dados JSON. O uso de cookies com solicitações entre domínios introduz duas vulnerabilidades de segurança:

  • Se o aplicativo for comprometido, os atacantes podem ter acesso aos cookies de todos os sites autenticados ao contexto local.
  • Todo o tráfego XMLHttpRequest que não seja SSL pode ser interceptado.

Devido a esses problemas, use XMLHttpRequest somente quando você precisar ter acesso autenticado e não se esqueça de usá-lo através de uma conexão SSL. Se você não precisar de acesso autenticado, use XDomainRequest. XDomainRequest permite o tráfego entre origens similar a um XMLHttpRequest, mas não usa cookies ou cabeçalhos de referência. Isso aumenta a segurança e a privacidade das solicitações entre domínios, conduzindo a um aplicativo mais seguro em todos os aspectos.

Restringir domínios de navegação

Um domínio de navegação do aplicativo é definido pelo manifesto do aplicativo, que reside no pacote do aplicativo. A restrição da lista de possíveis domínios de navegação é importante para evitar a possibilidade de que os invasores possam redirecionar uma sessão do aplicativo do usuário a um domínio que eles podem controlar, para que possam fazer ataques de phishing ou outras atividades prejudiciais.

Uma melhor prática simples é evitar o uso de curingas ao incluir URIs, porque muitos subdomínios de grandes serviços Web oferecem a capacidade de hospedar páginas arbitrárias ou outro conteúdo que um invasor pode aproveitar. Para saber mais, veja ApplicationContentUriRules.

Usar o controle WebView sempre que possível

O controle WebView tem mais medidas de segurança em vigor do que um iframe tradicional. Portanto, utilizar esse controle para a hospedagem de conteúdo da Web irá minimizar as chances de que um conteúdo da Web arbitrário comprometa o código do aplicativo. O WebView fornece os mesmos recursos de segurança para aplicativos da Windows Store em HTML/JavaScript e para aqueles em XAML. Usando ApplicationContentUriRules no manifesto do pacote, um desenvolvedor pode permitir a comunicação entre o controle WebView e o aplicativo de hospedagem. Além disso, existem maneiras de se comunicar com o conteúdo local. Para saber mais sobre a comunicação, veja os tópicos sobre novidades do WebView no Windows 8.1 e mesclagem de aplicativos e sites com HTML x-ms-webview.

Use o atributo HTML5 sandbox sempre que possível

O atributo HTML5 iframe sandbox impõe restrições adicionais sobre o conteúdo em um iframe. Embora o ambiente padrão do aplicativo da Windows Store que usa JavaScript forneça algumas proteções de segurança baseadas na origem do conteúdo, o atributo sandbox fornece uma camada adicional de defesa. Esse atributo ajuda os desenvolvedores a restringir conteúdo não confiável em uma página, como anúncios ou outro conteúdo arbitrário. A adição do atributo sandbox impede que o conteúdo:

  • Acesse o DOM da página pai
  • Execute scripts
  • Insira formulários
  • Leia ou grave cookies
  • Acesse o armazenamento local
  • Acesse bancos de dados SQL locais

O uso do atributo sandbox para restringir o acesso ao conteúdo da Web ao seu aplicativo pode aumentar significativamente a segurança do seu aplicativo.

Tópicos relacionados

Recursos e restrições por contexto
Inspecionar o seu gadget
Biblioteca de scripts contra cruzamento de sites
postMessage
invokeScriptAsync (HTML)
InvokeScriptAsync (XAML)

 

 

Mostrar:
© 2014 Microsoft