Boas Práticas de Segurança com Angular

angular security

Desenvolvimento de aplicativos sempre requer um cuidado especial no quesito segurança. Neste post falaremos de algumas das boas práticas de segurança para se aplicar em sistemas desenvolvidos com o framework Angular.

Manter todas as bibliotecas atualizadas

A equipe de desenvolvimento do Angular lança em intervalos regulares atualizações com aprimoramentos de recursos, correções de erros e principalmente correções de segurança. Portanto, recomenda-se atualizar as bibliotecas do Angular em intervalos breves. Não fazê-lo pode permitir que invasores ataquem o aplicativo ou site usando vulnerabilidades de segurança, muitas vezes públicas.

Prevenção contra Cross-Site Scripting (XSS)

O XSS permite que invasores injetem scripts do lado do cliente em páginas da Web visualizadas por outros usuários. Esse código pode, por exemplo, roubar dados do usuário ou executar ações para representar o usuário. Este é um dos ataques mais comuns na web.

Para bloquear sistematicamente os erros de XSS, o Angular trata todos os valores como não confiáveis por padrão. Quando um valor é inserido no DOM de um modelo, via propriedade, atributo, estilo, vinculação de classe ou interpolação, o Angular limpa e faz o escape dos valores não confiáveis.

Esta é a declaração dos provedores de sanitização no BrowserModule:

export const BROWSER_SANITIZATION_PROVIDERS: Array<any> = [
  {provide: Sanitizer, useExisting: DomSanitizer},
  {provide: DomSanitizer, useClass: DomSanitizerImpl},
];

@NgModule({
  providers: [
    BROWSER_SANITIZATION_PROVIDERS
    ...
  ],
  exports: [CommonModule, ApplicationModule]
})
export class BrowserModule {}

O Serviço de Sanitização DOM

O objetivo do DomSanitizer é limpar partes não confiáveis de valores.

Veja o esqueleto da classe:

export enum SecurityContext { NONE, HTML, STYLE, SCRIPT, URL, RESOURCE_URL }

export abstract class DomSanitizer implements Sanitizer {
  abstract sanitize(context: SecurityContext, value: SafeValue|string|null): string|null;
  abstract bypassSecurityTrustHtml(value: string): SafeHtml;
  abstract bypassSecurityTrustStyle(value: string): SafeStyle;
  abstract bypassSecurityTrustScript(value: string): SafeScript;
  abstract bypassSecurityTrustUrl(value: string): SafeUrl;
  abstract bypassSecurityTrustResourceUrl(value: string): SafeResourceUrl;
}

Como pode-se ver, existem dois tipos de padrões de métodos. O primeiro é o método sanitize, que obtém o contexto de um valor não confiável e retorna um valor confiável. O outro é o método bypassSecurityTrustX que a partir de valores não confiáveis retorna um objeto confiável.

O método Sanitize

Se um valor for confiável para o contexto, esse método de limpeza irá (no caso de um SafeValue) destrinchar o valor seguro contido e usá-lo diretamente. Caso contrário, o valor será limpo para estar seguro de acordo com o contexto de segurança.

Existem três funções auxiliares principais para limpar os valores. A função sanitizeHtml limpa o valor HTML não confiável analisando o valor e verifica seus tokens. As funções sanitizeStyle e sanitizeUrl limpam o estilo não confiável ou o valor da URL por expressões regulares.

Observe os exemplos abaixo:

var html = "<strong>hello world</strong>";
console.log(sanitizeHtml(html));
console.log(sanitizeHtml("<img src=x onerror=alert('img') />"));
console.log(sanitizeHtml("console.log('hello world')"));
console.log(sanitizeHtml("<script>alert('hello world')</script>"));
console.log(sanitizeUrl('http://example.com/</script>"><img src=x onerror="prompt(document.domain)">');
console.log(sanitizeStyle(".c{<script>alert('warning');</script>}");

Em situações específicas, pode ser necessário desativar a sanitização. Os usuários podem ignorar a segurança construindo um valor com um dos métodos bypassSecurityTrustX e vinculando a esse valor a partir do modelo.

import {BrowserModule, DomSanitizer} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `
    <div [innerHtml]="html"></div>
  `,
})
export class App {
  constructor(private sanitizer: DomSanitizer) {
    this.html = sanitizer.bypassSecurityTrustHtml('<h1>DomSanitizer</h1><script>ourSuperSafeCode()</script>') ;
  }
}

Política de Segurança de Conteúdo (CSP)

A CSP (Content Security Policy, política de segurança de conteúdo) é uma camada adicional de segurança que ajuda a detectar e atenuar certos tipos de ataques, incluindo XSS (Cross Site Scripting) e ataques de injeção de dados. Esses ataques são usados para tudo, desde roubo de dados a desfiguração ou distribuição de malware no site.

Para ativar o CSP, deve-se configurar o servidor da Web para retornar um cabeçalho HTTP Content-Security-Policy apropriado. Pode-se encontrar um manual muito detalhado sobre como habilitar o CSP no site do MDN. Há diversos validadores de CSP online que podem ser consultados.

Compilador de template AKA AOT-COMPILER

Os templates do Angular são iguais aos códigos executáveis: HTML, atributos e expressões de vinculação (mas não os valores vinculados) nos templates são confiáveis para serem seguros. Isso significa que, se um invasor puder controlar um valor que está sendo analisado pelo template, teremos um leak de segurança. Nunca deve-se gerar o código-fonte do template concatenando a entrada do usuário e os templates. Para evitar essas vulnerabilidades, deve-se usar o compilador de modelo off-line, também conhecido como injeção de modelo.

Abaixo as linhas de comando para ativar o AOT:

ng build --aot
ng serve --aot

Evitar o uso direto das APIs do DOM

As APIs do DOM no navegador integrado não protegem automaticamente contra vulnerabilidades de segurança. Por exemplo, “document”, o nó disponível por meio do ElementRef e muitas APIs de terceiros contêm métodos não seguros. Deve-se evitar interagir diretamente com o DOM e, em vez disso, usar Templates do Angular sempre que possível.

Proteção do XSS no lado do Servidor

Injetar código de templates em um aplicativo Angular é o mesmo que injetar código executável no aplicativo. Portanto, deve-se validar todos os dados no código do lado do servidor e fazer o escape adequadamente para evitar vulnerabilidades XSS no servidor. Além disso, a Angular recomenda não gerar templates no lado do servidor usando uma linguagem própria de templates.

Vulnerabilidades no nível HTTP

O Angular tem suporte integrado para ajudar a evitar duas vulnerabilidades comuns de HTTP: falsificação de solicitação entre sites (CSRF ou XSRF); e inclusão de script entre sites (XSSI). Ambos devem ser mitigados principalmente no lado do servidor, mas o Angular fornece ajudantes para facilitar a integração no lado do cliente.

Cross-site request forgery (XSRF)

A falsificação de requisições cross-site (também conhecida como ataque de um clique ou acesso à sessão) é abreviada como CSRF ou XSRF. É um tipo de exploração maliciosa de um site na Web em que comandos não autorizados são transmitidos de um usuário que o aplicativo da Web confia.

Em uma técnica comum anti-XSRF, o servidor de aplicativos envia um token de autenticação gerado aleatoriamente em um cookie. O código do cliente lê o cookie e adiciona um cabeçalho de solicitação personalizado com o token em todas as solicitações subsequentes. O servidor compara o valor do cookie recebido com o valor do cabeçalho da solicitação e rejeita a solicitação se os valores estiverem ausentes ou não corresponderem.

Essa técnica é eficaz porque todos os navegadores implementam a mesma política de origem. Apenas o código do site no qual os cookies estão definidos pode ler os cookies desse site e definir cabeçalhos personalizados em solicitações para esse site. Isso significa que somente seu aplicativo pode ler esse token de cookie e definir o cabeçalho personalizado.

O HttpClient Angular fornece suporte interno para fazer verificações no lado do cliente. Se precisar, consulte o Suporte do Angular para XSRF.

Cross-site script inclusion (XSSI)

A inclusão de scripts cross-site (também conhecida como vulnerabilidade JSON) pode permitir que o site de um invasor leia dados de uma API JSON. O ataque funciona em navegadores mais antigos, substituindo os construtores de objetos JavaScript nativos e incluindo uma URL de API usando uma tag <script>. Esse ataque só será bem-sucedido se o JSON retornado for executável como JavaScript.

Os servidores podem evitar um ataque prefixando todas as respostas JSON para torná-las não executáveis, por convenção, usando a conhecida string:

")]}',\n"

A biblioteca HttpClient do Angular reconhece essa convenção e automaticamente tira a string:

")]}',\n"

de todas as respostas antes de uma análise mais aprofundada.

Conclusão

O Angular através de seus métodos sanitizantes dá uma grande segurança a clientes e dados de aplicações. Contudo todos os itens listados neste post devem ser levados em consideração para que a aplicação esteja de acordo com as melhores práticas de desenvolvimento do mercado.

*** A OctalMind é uma empresa especializada no desenvolvimento de sistemas de alta tecnologia.