Conheça as políticas experimentais de integridade do Node.js
21 de março de 2019
0 minutos de leituraUm recurso experimental recente para implementar políticas de integridade chegou ao núcleo do Node.js 11.8.0. Disponível até agora apenas em uma versão que não é LTS, esse recurso verifica a integridade do ambiente de execução do Node.js durante o carregamento dos módulos, para confirmar que o código deles não foi adulterado.
Bradley Farias introduziu essa mudança em outubro de 2018 e se inspirou em um recurso de segurança semelhante usado em navegadores: Subresource Integrity.
Subresource Integrity
O World Wide Web Consortium (W3C) propôs um novo campo integrity para a especificação HTML, que permite verificar subrecursos em um documento HTML. As páginas da Web podem instruir o navegador a carregar recursos por meio de uma tag script ou link. No entanto, sem um campo de integridade nesses elementos HTML, não há como verificar se um recurso foi adulterado.
As páginas da Web carregam recursos próprios ou de terceiros de um servidor remoto, geralmente por meio de uma rede de distribuição de conteúdo (CDN). Ao carregar esses recursos, verificar a integridade dos arquivos ajuda a proteger contra agentes mal-intencionados. Alguns exemplos:
Um servidor remoto comprometido que pode fornecer cópias modificadas do arquivo de recurso
Um meio de transporte comprometido e seu arquivo de recurso
Políticas de integridade para módulos do Node.js
Inspirados pelo mecanismo de segurança dos navegadores para garantir a integridade dos recursos, podemos nos perguntar: e se o Node.js também pudesse fazer isso com módulos de terceiros, verificando-os antes de carregá-los na memória e executá-los, quando são requisitados pelo código do programa?
O novo recurso experimental de políticas do Node.js 11.8.0 permite impor esse comportamento usando a flag de linha de comando --experimental-policy, que exige um manifesto de políticas para todos os recursos de um projeto. Vamos ver como funciona!
Um manifesto de políticas do Node.js
A versão 11.8.0 oferece apenas a aplicação das políticas pelo carregador de módulos, mas o Node.js ainda não consegue processar o manifesto de políticas. Para gerenciar o arquivo de políticas, podemos usar o auxiliar de linha de comando node-policy, criado pelo próprio Bradley:
Com o comando integrity:add do node-policy, podemos criar um manifesto de políticas com todos os hashes criptográficos gerados para os arquivos do diretório atual. Isso inclui desde o diretório .git/ até todo o conteúdo de node_modules/, então pode levar um tempinho para gerar tudo.
Para demonstrar como isso funciona, vamos usar um módulo de linha de comando do Node.js que criei para me ajudar a exportar resultados de pesquisas do typeform.
Execute o node-policy para criar um arquivo de manifesto de integridade para todos os arquivos do diretório atual (indicado pelo último argumento, o ponto) e especifique o algoritmo a ser usado como função de hash criptográfico. As opções disponíveis são sha256, sha384 e sha512, conforme a especificação HTML de Subresource Integrity.

O arquivo de políticas gerado para o projeto é salvo no diretório pessoal do usuário. Veja um pequeno trecho de .node-policy.json, que mostra a estrutura do manifesto, com os URLs dos arquivos e seus hashes de integridade:
Se executarmos a CLI node-policy em outros diretórios de projeto, mais arquivos serão adicionados a esse manifesto de políticas. Esse é o funcionamento do node-policy, não uma especificação ou diretriz.
Por que o node-policy cria o arquivo de políticas no diretório pessoal do usuário? Embora ainda não tenhamos padronizado as práticas recomendadas para políticas de integridade, esse arquivo é a fonte confiável dos recursos autorizados. Por isso, é melhor protegê-lo contra qualquer tentativa de adulteração. Duas boas práticas são deixar o arquivo somente para leitura e armazená-lo fora de qualquer diretório que possa ser acessado.
Para simular a adulteração de um arquivo e mostrar como o Node.js detecta o problema, fiz uma pequena alteração no código de bin/cli.js, que faz parte do projeto da CLI. Ao executar o código JavaScript da CLI no Node.js, ele detecta que o hash é diferente antes de carregar esse módulo CommonJS e gera um erro, retornando o Node.js ao prompt de comando.

A implementação atual permite registrar incompatibilidades de integridade em vez de gerar um erro ou encerrar o programa. Isso é possível com uma propriedade onerror, que pode ser adicionada ao objeto de nível superior do arquivo de manifesto de políticas.
Resumo
O trabalho contínuo para incorporar recursos de segurança ao Node.js é promissor, e certamente veremos mais novidades em breve. Vale lembrar que o recurso de políticas de integridade ainda é experimental e está disponível apenas a partir do Node.js 11.8.0.
Comece a resolver desafios de capture the flag
Aprenda a resolver desafios de capture the flag assistindo sob demanda ao nosso workshop virtual introdutório.
