Skip to main content

Comparação de frameworks web para Node.js: qual é o mais seguro?

Escrito por
prioritize the security backlog

8 de março de 2023

0 minutos de leitura

JavaScript é a linguagem de programação mais popular do mundo e oferece diversos frameworks web que ajudam desenvolvedores a criar aplicações web seguras e confiáveis com Node.js. Cada framework tem recursos próprios. A escolha certa para você depende das suas preferências e do tipo de aplicação que pretende criar.

Com tantos frameworks disponíveis, você precisa de uma maneira de avaliar a segurança deles. Neste artigo, vamos analisar três frameworks populares — Express.js, NestJS e Fastify — e avaliar o quanto eles seguem as práticas recomendadas de segurança para Node.js.

Comparação da segurança dos frameworks web para Node.js

Todos os frameworks web baseados em JavaScript são construídos sobre o runtime do Node.js. Aplicações que usam o ecossistema npm geralmente combinam muitas dependências do npm para adicionar funcionalidades. Por isso, independentemente do framework usado, vulnerabilidades no Node.js e nas dependências do npm provavelmente afetarão a aplicação. A segurança da aplicação depende da adoção de práticas recomendadas e princípios de design durante o desenvolvimento.

Os frameworks web incentivam o uso dos pacotes mais recentes e a atualização frequente deles. Eles oferecem uma camada de abstração que reduz a possibilidade de acesso não autorizado à aplicação. Por esses motivos, devemos usar um framework web ao criar aplicações.

Nas próximas seções, vamos discutir e comparar os recursos de segurança dos nossos três frameworks para Node.js.

Express.js

Express.js é um framework web rápido e minimalista para Node.js, desenvolvido para criar aplicações web e APIs com as stacks MERN ou MEAN. O framework incentiva desenvolvedores a seguir suas diversas práticas recomendadas de segurança antes de implantar aplicações em produção. Além disso, o Express.js segue as práticas recomendadas de segurança do Node.js e oferece várias recomendações para colocá-las em prática:

Prevenção de ataques de força bruta

A prática recomendada 6.12 do Node.js aborda a prevenção de ataques de força bruta contra mecanismos de autorização. Ela recomenda implementar uma estratégia para limitar o número de tentativas de login em rotas sensíveis, como /admin ou /login, reduzindo o risco de ataques de força bruta e de dicionário contra senhas. Podemos fazer isso com o pacote npm rate-limiter-flexible, limitando as tentativas de login com base no endereço IP de origem da solicitação ou em parâmetros do corpo da solicitação, como nome de usuário ou endereço de e-mail. Com base nessas propriedades, podemos criar um limitador que conta e restringe o número de tentativas consecutivas malsucedidas. Depois, podemos adicionar outro limitador para bloquear um endereço IP por um período determinado quando o limite de tentativas malsucedidas consecutivas for atingido. O Express.js segue essa recomendação ao sugerir o mesmo pacote npm e bloquear tentativas de autorização com base nas mesmas métricas.

Garantia da segurança de expressões regulares

A prática recomendada 6.16 do Node.js recomenda o uso de pacotes de terceiros para validar expressões regulares, como validator.js e safe-regex, a fim de detectar padrões vulneráveis. Ela desaconselha criar suas próprias expressões regulares, pois expressões mal escritas são suscetíveis a ataques de DoS por regex e podem ser exploradas facilmente para bloquear completamente os event loops.

Configuração adequada de cabeçalhos HTTP

A prática recomendada 6.6 recomenda o uso de cabeçalhos seguros para proteger aplicações contra vulnerabilidades como cross-site scripting, sequestro de cookies e clickjacking. Anteriormente, o Express.js sofreu uma vulnerabilidade de segurança no módulo forwarded, que processa o cabeçalho X-Forwarded-For. Para explorar essa falha, um agente malicioso poderia criar uma consulta que, ao ser analisada, bloqueava um event loop necessário e resultava em uma resposta de negação de serviço. Para evitar essa e outras vulnerabilidades semelhantes, o Express.js incorpora o Helmet para facilitar a configuração dos cabeçalhos relacionados à segurança e seguir as práticas recomendadas do Node.js.

NestJS

O NestJS é um framework de aplicações web fortemente inspirado no Angular, um framework front-end. Ele foi desenvolvido para criar aplicações back-end escaláveis. Como funciona como uma camada sobre o Fastify ou o Express, o NestJS geralmente oferece o mesmo nível de segurança desses frameworks. Sua principal vantagem está nas arquiteturas e estruturas que disponibiliza para usarmos no desenvolvimento de aplicações.

O NestJS é desenvolvido com TypeScript e oferece suporte a essa linguagem, permitindo criar aplicações mais fáceis de manter e mais complexas. Ele também conta com Guards, que podem determinar se um manipulador de rota deve processar uma solicitação específica.

Diagrama de fluxo que mostra uma solicitação HTTP passando do lado do cliente por um guard até um manipulador de rota

Esse framework segue as práticas recomendadas de segurança do Node.js de várias maneiras:

Criptografia e hashing

A prática recomendada 6.8 recomenda aplicar hashing aos dados sensíveis dos usuários (por exemplo, senhas), em vez de armazená-los como texto simples. Essa prática lista três funções que devem ser usadas, no mínimo, mas também recomenda parâmetros de nível mais alto e combinações exclusivas para cada programa, a fim de reduzir os danos caso um agente malicioso descubra o método de hash. Além disso, recomenda adicionar um salt antes de aplicar hashing às senhas. O NestJS segue essa prática ao recomendar a criptografia e o hashing das informações. Para criptografia, o framework incentiva o uso do módulo crypto integrado. Para hashing, recomenda os pacotes bcrypt ou argon2.

Validação de solicitações recebidas

A prática recomendada 6.10 do Node.js recomenda validar o corpo das solicitações recebidas. Isso significa definir quais dados a aplicação deve aceitar e rejeitar imediatamente qualquer formato diferente. Essa medida ajuda a reduzir ataques de DDoS, pois impede que um invasor envie dados personalizados com estrutura, valor e tamanho diferentes. O NestJS facilita a implementação dessa prática ao oferecer várias pipes prontas para uso, que podem ser usadas para realizar a validação.

Alteração das configurações do middleware de sessão

A prática recomendada 6.22 do Node.js recomenda ajustar as configurações padrão de cookies para aumentar a proteção dos usuários e da aplicação, reduzindo ataques como identificação e sequestro de sessões. O NestJS facilita a implementação dessa prática oferecendo uma maneira de alterar as configurações da sessão. Um exemplo de vulnerabilidade de segurança que afetou esse framework foi encontrado no módulo @finastra/nestjs-proxy, um módulo de proxy para NestJS. As versões afetadas desse pacote eram vulneráveis à exposição de informações, causada pelo encaminhamento padrão de cookies sensíveis.

Fastify

Fastify é um framework web para Node.js que tem como objetivo oferecer velocidade e baixo overhead. Inspirado em Hapi e Express, ele foi desenvolvido para servir como uma base simples e estável para criar aplicações e serviços web. O Fastify tem uma base de código enxuta e oferece uma configuração simples e declarativa, que permite iniciar um servidor rapidamente.

Esse framework segue as práticas recomendadas de segurança do Node.js ao recomendar:

O uso de fastify/rate-limit para limitar as solicitações dos clientes

Isso está de acordo com a prática recomendada 6.12. Segundo essa prática, limitar a taxa de solicitações ajuda a prevenir ataques de força bruta contra mecanismos de autorização em rotas com privilégios elevados, como /login e /admin. É possível fazer isso criando limitadores com base em duas métricas, conforme explicado aqui.

O uso de fastify/helmet para configurar cabeçalhos de segurança importantes

Isso está de acordo com a prática recomendada 6.6. A configuração adequada dos cabeçalhos de segurança protege a aplicação contra cross-site scripting, clickjacking e outros ataques.

O uso do plugin fastify-cockroachdb fornecido pela comunidade

Esse plugin permite que desenvolvedores conectem uma instância PostgreSQL do CockroachDB por meio do ORM Sequelize. De acordo com a prática recomendada 6.4, bibliotecas ORM/DRM ajudam a prevenir injeções de SQL/NoSQL ao evitar o uso de concatenação de strings e template strings do JavaScript, que expõem uma aplicação a vários tipos de ataque. Essa abordagem também favorece o uso de bibliotecas de acesso a dados confiáveis, como Sequelize, Knex e mongoose, que oferecem proteção integrada contra ataques de injeção.

Limitação de solicitações simultâneas

A prática recomendada 6.2 do Node.js incentiva a implementação de um limitador de taxa, que pode ajudar a evitar um número excessivo de solicitações simultâneas — a base dos ataques de DoS. Essa prática recomenda o uso de um serviço desenvolvido para essa finalidade. O Fastify oferece o plugin @fastify/rate-limit para ajudar nessa tarefa.

Remoção de segredos dos arquivos de configuração

A prática recomendada 6.3 do Node.js recomenda armazenar chaves e segredos de forma criptografada ou usar variáveis de ambiente. Armazená-los como texto simples facilita que sejam descobertos. O Fastify segue essa prática oferecendo o plugin @fastify/env, que permite verificar e carregar arquivos de configuração. Ainda assim, deve-se evitar carregar segredos de variáveis de ambiente, recorrendo a essa opção apenas como último recurso.

Uma limitação de segurança desse framework é não oferecer suporte ao bloqueio de tokens JSON Web (JWTs). O bloqueio de JWTs ajuda a impedir que um invasor use tokens expirados ou perdidos para se passar pelo proprietário do token.

Um exemplo recente de vulnerabilidade de segurança nesse framework é o ataque de DoS que afetou algumas de suas versões.

Como escolher o framework certo

Todos os frameworks web abordados neste artigo seguem as práticas recomendadas de segurança em um nível satisfatório. No entanto, o NestJS é o que mais se aproxima das práticas recomendadas de segurança do Node.js: ele oferece uma camada de abstração sobre o Express.js com recursos de segurança integrados, dificultando o acesso de invasores ao sistema.

Cada um dos frameworks analisados tem seus pontos fortes e casos de uso ideais. Todos também oferecem suporte a pacotes adicionais que você pode integrar para criar aplicações seguras e robustas.

Por exemplo, o Express.js é o framework mais popular e consolidado, com excelente documentação e amplo apoio da comunidade.

O NestJS é uma boa opção para aplicações escaláveis, pois conta com muitos pacotes integrados, oferece uma camada de abstração sobre o Express.js e dá suporte a TypeScript. Já o Fastify prioriza aplicações web rápidas e eficientes sem abrir mão da segurança.

Independentemente do framework que você usa, como desenvolvedor, é essencial escolher as dependências adequadas e seguir as práticas recomendadas de segurança ao criar uma aplicação web. Também é fundamental atualizar os pacotes para as versões mais recentes e eliminar vulnerabilidades conhecidas.

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.

Leia mais

blog feature snyk container custom base recommendations
Blog

Conheça o Evo Agentic AppSec: segurança que acompanha o ritmo do desenvolvimento com IA

O desenvolvimento impulsionado por IA está avançando mais rápido do que os fluxos de trabalho de segurança tradicionais. O AppSec agentivo da Snyk usa agentes de segurança para encontrar, corrigir e verificar vulnerabilidades continuamente, enquanto as pessoas definem os critérios.

feature insights context
Blog

Os ataques autônomos já chegaram. A defesa precisa acompanhar o ritmo.

Os atacantes autônomos estão reduzindo o tempo disponível para a defesa. Saiba como a descoberta, a correção, a validação e a prevenção contínuas ajudam as equipes de segurança a acompanhar esse ritmo.

illustration hero ai
Blog

O furacão da IA chegou

A IA está acelerando tanto a criação de software quanto os ataques cibernéticos. As lideranças devem proteger agentes e código desde o início, aplicar controles em tempo de execução e validar as defesas de forma independente.