In this article
10 práticas recomendadas para a segurança do Node.js
O que é Node.js?
Node.js é uma plataforma de desenvolvimento de aplicações web de código aberto e multiplataforma. Trata-se de um ambiente de execução JavaScript, criado com base no mecanismo V8 do Chrome, que permite aos desenvolvedores criar aplicações web escaláveis de forma rápida e fácil.
O que é segurança no Node.js?
O Node.js em si é uma plataforma segura, mas muitos pacotes de código aberto de terceiros do ecossistema podem não ser. Esses pacotes são usados por meio do Node Package Manager (NPM) e estão sujeitos a diversos tipos de vulnerabilidades e outros riscos de licenciamento e segurança do Node.js. Algumas bases de código Node.js têm milhares desses pacotes, expondo as aplicações que os utilizam a muitos riscos.
Por que proteger o Node.js?
O NPM, geralmente usado com o ambiente de execução Node.js, é um dos maiores ecossistemas de pacotes de código aberto. Tecnologias de código aberto podem representar uma preocupação significativa em relação à cibersegurança. Na verdade, o relatório State of Open Source Security da Snyk mostra que um projeto médio tem 49 vulnerabilidades em 79 dependências diretas. Além disso, um desenvolvedor no GitHub realizou um experimento de segurança e conseguiu acessar 14% dos pacotes do NPM; outros 54% poderiam ser alcançados por meio de cadeias de dependências.
Isso mostra que o Node.js não é seguro o suficiente para que os desenvolvedores ignorem a possibilidade de exposição a hackers. Além destas dez práticas recomendadas de segurança para o NPM, recomendamos as práticas adicionais abaixo para garantir a segurança das aplicações criadas com Node.js.
10 práticas recomendadas para manter a segurança do Node.js
Para combater os riscos mais comuns do Node.js, é importante adotar algumas práticas recomendadas. Estas são as dez práticas mais eficazes para ajudar você a evitar armadilhas comuns de segurança no Node.js.
1. Configure o registro de logs e o monitoramento
O registro de logs e o monitoramento são essenciais para manter a segurança do Node.js. Acompanhar os logs permite entender o que está acontecendo na aplicação e investigar qualquer atividade suspeita. Alguns níveis importantes para registrar são info, error, warn e debug. Para reduzir o trabalho manual, você pode usar módulos como Bunyan e toobusy-js para automatizar o registro de logs e o monitoramento.
2. Adote políticas de autenticação robustas
Você deve ter percebido que vários dos possíveis ataques mencionados acima envolvem um agente mal-intencionado que contorna ou explora a autenticação de usuários. Adotar políticas de autenticação robustas é uma proteção importante contra esses ataques. Confira algumas recomendações:
Exija autenticação multifator (MFA) e logon único (SSO).
Prefira as bibliotecas Scrypt ou Bcrypt à biblioteca crypto do Node.js.
Implemente políticas consistentes de gerenciamento de sessões.
Exija senhas fortes dos usuários.
Limite o número de tentativas de login malsucedidas.
3. Evite bloquear o event loop
Quando se trata do event loop e das threads do pool de workers, executar tarefas pesadas em qualquer um deles pode interromper as respostas às requisições de outros clientes e prejudicar a capacidade de processamento. Veja algumas maneiras de manter suas threads disponíveis:
Garanta que seus callbacks JavaScript sejam executados rapidamente.
Reduza a complexidade dos callbacks mantendo constante o número de etapas, independentemente do argumento. Assim, cada cliente na fila terá uma chance justa.
Se uma tarefa for complexa, limite a entrada e rejeite entradas muito longas. Com entradas limitadas, a execução não ultrapassa o tempo necessário para processar a entrada no pior cenário, evitando que a thread seja bloqueada. (Antes, é claro, verifique se esse tempo é curto o suficiente para não bloquear a thread.)
Evite usar APIs síncronas dos módulos de criptografia, compactação, sistema de arquivos ou processos filhos. Elas podem levar muito tempo para serem concluídas e bloquear o event loop.
4. Trate os erros com segurança
Muitos problemas de desempenho e segurança de aplicações podem ser evitados preparando o código para lidar com erros. Confira algumas práticas recomendadas para manter seus programas sem bugs:
Em vez de gerenciar erros assíncronos com callbacks, use uma biblioteca de promises confiável ou async/await.
O tratamento de erros personalizado ou baseado em strings aumenta a complexidade. Simplifique-o usando sempre o objeto de erro integrado.
Tratar erros no middleware pode duplicar o código. O ideal é gerenciar a lógica de tratamento em um local centralizado.
Teste regularmente os fluxos de tratamento de erros para garantir que não gerem falsos positivos nem deixem erros passarem despercebidos.
Use uma ferramenta de gerenciamento de processos para reiniciar a aplicação quando ocorrer um erro desconhecido. Pm2 e forever são exemplos de ferramentas de gerenciamento de processos do Node.js.
5. Não envie informações desnecessárias
Ao enviar informações para o front-end, envie apenas os dados essenciais. Em teoria, você pode filtrar as informações que deseja exibir, mas os invasores ainda podem acessar dados ocultos pelo back-end. A única maneira de garantir que eles não acessem dados confidenciais é simplesmente não enviá-los, a menos que seja absolutamente necessário.
6. Limite o tamanho das requisições
No Node.js, o limite padrão para as requisições é de 5 MB. Para evitar um ataque DDoS em que um hacker sobrecarrega seus servidores, você pode reduzir ainda mais o tamanho das requisições aceitas pelo Node.js.
Confira duas maneiras simples de fazer isso:
Configure a opção ‘limit’ no pacote body-parser para aceitar apenas payloads pequenos.
Use proxies reversos ou o middleware do Express para definir limites de tamanho para determinados tipos de conteúdo.
7. Valide as entradas do usuário
Um dos motivos pelos quais agentes mal-intencionados conseguem realizar ataques XSS é a falta de validação das entradas do usuário. O primeiro passo é higienizar essas entradas com um pacote do NPM, como o DOMPurify. Depois, use uma biblioteca de validação de formulários, como express-validator ou XSS-filters. Essas bibliotecas automatizam a tarefa repetitiva de validar cada entrada em cada requisição. Filtros de saída que levam o contexto em conta, como o XSS-filters, são fáceis de usar pelos desenvolvedores e codificam o número mínimo de caracteres necessário para impedir um ataque XSS.
8. Garanta a desserialização segura
O Node.js não oferece formas avançadas de serialização de objetos. Por isso, invasores podem usar objetos serializados para transferir payloads. Implemente verificações de integridade e autenticação do usuário e higienize os dados desserializados para evitar esse problema. Em mais detalhes, use tokens anti-CSRF, cabeçalhos de requisição personalizados, a flag SameSite em sessões de cookies e proteção baseada na interação do usuário.
9. Use linters de segurança e ferramentas SAST
Para corrigir vulnerabilidades que podem levar a um ataque, primeiro é preciso saber onde elas estão. Ferramentas como plugins de linter e testes estáticos de segurança de aplicações (SAST) podem automatizar esse processo e ajudar você a não deixar nada passar.
Linters como o eslint-plugin-node-security analisam o código-fonte para identificar e destacar práticas inseguras. Ferramentas SAST como o Snyk Code monitoram seu código Node.js enquanto você escreve e alertam sobre possíveis vulnerabilidades.
Comece a jogar Capture the Flag
Aprenda a resolver desafios de Capture the Flag assistindo à gravação sob demanda do nosso workshop virtual introdutório.
10. Execute o Node.js como um usuário sem privilégios de root
Essa é uma boa prática em qualquer situação, mas é especialmente importante não executar o Node.js como usuário root. Ao executá-lo como um usuário sem privilégios de root, você limita a superfície de ataque que agentes mal-intencionados podem explorar.
Essa recomendação segue o princípio do menor privilégio: conceda aos usuários apenas o nível de acesso necessário para realizar suas tarefas. O acesso root só deve ser concedido em situações muito específicas.
A Snyk contribui para a segurança do Node.js
Desde maio de 2021, a Snyk contribui para a segurança do ecossistema Node.js ao assumir o programa de divulgação de vulnerabilidades desse ecossistema. A equipe dedicada de analistas e pesquisadores de segurança da Snyk faz a triagem e a verificação dos relatos de vulnerabilidades do Node.js e entra em contato com os mantenedores dos pacotes afetados para iniciar o processo de divulgação responsável, conforme a política de divulgação da Snyk.
Além disso, os produtos da Snyk permitem encontrar e corrigir vulnerabilidades em cinco minutos. Veja como a Snyk aprimora a segurança no Node.js:
Snyk Open Source ajuda a identificar vulnerabilidades nas dependências de uma aplicação Node.js e a alertar os desenvolvedores sobre elas. Assim, seu código fica protegido contra os principais riscos de segurança abordados neste artigo.
Snyk Code é uma ferramenta SAST que ajuda a identificar vulnerabilidades no código da aplicação e alertar os desenvolvedores sobre elas.
Snyk Container ajuda os desenvolvedores a encontrar vulnerabilidades em contêineres e cargas de trabalho do Kubernetes ao longo de todo o ciclo de vida do desenvolvimento de software (SDLC).
Se você usa Node.js em contêineres, também temos práticas recomendadas para conteinerizar aplicações Node.js com Docker.
Snyk para a segurança de JavaScript
Da primeira linha de código à última dependência npm, a Snyk mantém seus aplicativos JavaScript seguros diretamente no IDE, na CLI e nos fluxos de trabalho do Git.
Perguntas frequentes sobre segurança do Node.js
O Node.js é seguro?
A plataforma Node.js é segura por natureza, mas, como utiliza pacotes de código aberto de terceiros por meio do sistema de gerenciamento de pacotes npm, está sujeita a ataques cibernéticos. Para manter a segurança do Node.js, as empresas devem adotar as práticas recomendadas, como as apresentadas neste artigo.
Como proteger o Node.js?
Adotar práticas como validar as entradas dos usuários, implementar autenticação, limitar o tamanho das solicitações e configurar logs e monitoramento são bons primeiros passos para proteger o Node.js. Para saber mais sobre ataques de injeção de código, confira cinco maneiras de prevenir a injeção de código no Node.js.
O Node.js pode ser hackeado?
Hackers podem invadir aplicações Node.js sobrecarregando servidores de produção, injetando JavaScript malicioso ou enviando entradas que exigem muito tempo de processamento nos seus programas. A natureza de código aberto do NPM também deixa o Node.js exposto a vulnerabilidades.