5 trechos de código de segurança em Node.js que todo desenvolvedor backend deve conhecer
28 de fevereiro de 2024
0 minutos de leituraComo desenvolvedores backend, temos a importante responsabilidade de garantir a segurança das nossas aplicações. O Node.js não é exceção, e sua popularidade crescente o torna um alvo atraente para hackers. Por isso, é fundamental seguir as melhores práticas de segurança ao trabalhar com Node.js.
Neste artigo, vamos explorar alguns trechos essenciais de código de segurança em Node.js que todo desenvolvedor backend deve conhecer em 2024. Vulnerabilidades em softwares Node.js podem representar uma ameaça significativa para qualquer aplicação. Elas podem levar a acessos não autorizados, vazamentos de dados e, nos piores casos, ao comprometimento total do sistema. Por isso, seguir as melhores práticas de segurança não é apenas uma recomendação: é uma necessidade.
No contexto do Node.js, isso significa garantir que seu código não exponha brechas que possam ser exploradas. Também significa higienizar as entradas dos usuários para evitar ataques de injeção, tratar as senhas corretamente como dados confidenciais e gerenciar dependências para evitar vulnerabilidades de terceiros, entre outras práticas.
Vamos analisar os seguintes conceitos de segurança em Node.js e os respectivos trechos de código, considerando sua eficácia na prevenção de vulnerabilidades comuns e a facilidade de uso por desenvolvedores sem experiência adicional em segurança:
Use o modelo de permissões do Node.js para restringir o acesso a recursos durante a execução
Implemente a validação de entradas com um schema JSON do Fastify
1. Use o modelo de permissões do Node.js para restringir o acesso a recursos durante a execução
O modelo de permissões do Node.js pode ter um papel fundamental na proteção das suas aplicações. Ele é uma parte importante do modelo de segurança principal do Node.js e ajuda a proteger suas aplicações contra ataques e atividades maliciosas. Assim como o Deno trouxe a promessa de restringir recursos com base em processos, o Node.js agora oferece algo semelhante com seu modelo de permissões — até certo ponto.
Imagine que uma aplicação Node.js precisa converter arquivos PDF em imagens PNG. Podemos usar o pacote npm pdf-image para realizar essa tarefa. O pacote pdf-image usa processos filhos para fazer a conversão. Para habilitar esse recurso, precisamos usar a flag --allow-child-process no runtime do Node.js (disponibilizada pelo modelo de permissões).
Veja abaixo um trecho de código que demonstra isso:
Neste trecho, criamos uma nova instância de PDFImage com o caminho do nosso arquivo PDF e algumas opções de conversão. Em seguida, chamamos convertFile() para converter o PDF em uma imagem PNG.
Se você habilitar o modelo experimental de permissões no Node.js, precisará executar explicitamente o runtime do Node.js com a flag de linha de comando --allow-child-process mencionada acima, pois, nos bastidores, a biblioteca pdf-image inicia um processo filho para converter os PDFs.
Embora o modelo de permissões do Node.js seja uma ótima maneira de restringir o acesso aos recursos do sistema, também é fundamental estar ciente das possíveis vulnerabilidades de segurança nos pacotes que usamos. É aí que entra a extensão do Snyk para Visual Studio Code. A extensão do Snyk pode detectar código inseguro e dependências vulneráveis em uma aplicação Node.js. Por exemplo, sabe-se que o pacote pdf-image mencionado anteriormente é vulnerável a injeção de comandos por usar processos filhos. Essa vulnerabilidade é conhecida desde 2018 e, infelizmente, ainda não há uma correção disponível.
Isso destaca a importância de usar ferramentas como o Snyk para ficar por dentro das vulnerabilidades de segurança nos pacotes dos quais dependemos. Também serve como lembrete de que precisamos ter cuidado ao usar determinados recursos, como processos filhos, que podem trazer riscos de segurança se não forem tratados corretamente.
Como desenvolvedores Node.js, temos a responsabilidade de garantir que o código que escrevemos seja não apenas funcional, mas também seguro. Uma maneira importante de aumentar a segurança de uma aplicação Node.js é usar o modelo de permissões integrado para restringir o acesso aos recursos do sistema durante a execução. Se você sabe que sua aplicação Node.js não precisa de recursos de processos filhos, não habilite esse recurso para evitar ampliar a superfície de ataque.
Comece a proteger seus aplicativos JavaScript
Encontre e corrija vulnerabilidades em JavaScript gratuitamente com o Snyk.
Não é necessário informar um cartão de crédito.
Ou cadastre-se com o Azure AD Docker ID Bitbucket
Ao usar o Snyk, você concorda em cumprir nossas políticas, incluindo os Termos de Serviço e a Política de Privacidade.
Perguntas frequentes sobre o modelo de permissões do Node.js
Quais ameaças à segurança o modelo de permissões do Node.js ajuda a prevenir?
O modelo de permissões do Node.js foi criado para ajudar a prevenir várias ameaças à segurança, incluindo acesso não autorizado a arquivos, ataques de injeção de comandos e escalonamento de privilégios.
Posso personalizar o modelo de permissões do Node.js?
Sim, alguns dos recursos controlados pelo modelo de permissões do Node.js podem ser altamente personalizados. Por exemplo, ao limitar o acesso a recursos de arquivos, você pode especificar diferentes arquivos ou caminhos, como --allow-fs-read=*.
O modelo de permissões do Node.js é suficiente para proteger meus aplicativos?
Embora o modelo de permissões do Node.js seja uma parte fundamental da segurança de aplicativos, ele não é suficiente por si só. Também é importante adotar práticas de programação segura, auditar regularmente o código em busca de vulnerabilidades, verificar se há vulnerabilidades nas dependências de terceiros e usar ferramentas como o Snyk para identificar e corrigir possíveis problemas de segurança.
2. Implemente a validação de entradas com um schema JSON do Fastify
A validação de entradas é uma parte essencial do desenvolvimento backend. Se você já criou APIs com Express, Fastify ou outros frameworks, provavelmente já percebeu sua importância. Essa prática de segurança garante que apenas dados formatados corretamente entrem no seu sistema, evitando possíveis riscos. Uma maneira de implementar a validação de entradas nas suas aplicações Node.js é usar o schema do Fastify nas suas aplicações web Fastify.
Abordagem baseada em schema do Fastify
O Fastify usa uma abordagem baseada em schema para validar entradas. Embora não seja obrigatório, recomendamos usar o schema JSON para validar suas rotas e serializar suas saídas. O schema JSON define um contrato para seus dados, detalhando o formato esperado, os tipos de dados, os campos obrigatórios e outras restrições. Você pode pensar no schema JSON das rotas do Fastify como uma forma de usar TypeScript para garantir a tipagem forte do código durante o processo de compilação.
Imagine uma aplicação Fastify simples na qual criamos um novo usuário. Podemos usar um schema do Fastify para validar os dados de entrada.
No código acima, definimos um UserSchema que exige nome, e-mail e senha. O e-mail deve estar em um formato válido, e a senha precisa ter pelo menos 8 caracteres.
Ignorar a validação de entradas pode expor sua aplicação a vários riscos de segurança, incluindo falsificação de solicitação do lado do servidor (SSRF) ou ataques de poluição de parâmetros HTTP. Ataques SSRF podem induzir o servidor a fazer solicitações não autorizadas, o que pode expor dados. Já a poluição de parâmetros HTTP pode manipular ou corromper solicitações e causar comportamentos inesperados.
Ferramentas como o Snyk podem ajudar a encontrar essas vulnerabilidades ao analisar seu código em busca de falhas de segurança. Elas também podem oferecer orientações de correção para ajudar você a resolver esses problemas e aumentar a segurança geral da sua aplicação.
Perguntas frequentes sobre validação de entradas com Fastify
A validação de entradas é necessária?
Sim. A validação de entradas é uma prática fundamental de segurança que impede que dados em formato inadequado entrem no seu sistema.
Posso usar outras bibliotecas de validação com o Fastify?
Sim, o Fastify é flexível e permite usar outras bibliotecas de validação, como Joi, yup ou ajv.
A validação de esquema do Fastify afeta o desempenho?
O Fastify foi desenvolvido para oferecer alto desempenho, e a validação de esquema tem impacto mínimo na performance.
4. O que é um esquema JSON do Fastify?
Os esquemas do Fastify são usados para validar os dados de requisição e resposta nas suas rotas, garantindo que apenas dados que atendam aos critérios especificados sejam processados. Isso reduz o risco de processar dados inválidos que poderiam causar vulnerabilidades de segurança ou erros na aplicação.
3. Armazene senhas com hash seguro usando Bcrypt
Armazenar senhas de usuários com segurança é fundamental no desenvolvimento de software. Em caso de violação de dados, você quer garantir que as informações de senha dos usuários não possam ser decifradas facilmente. É aí que entra o hashing de senhas. Hashing é o processo de converter uma chave em outro valor. Uma função de hash gera esse novo valor e, idealmente, produz uma saída única (ou código hash) para cada valor de entrada.
Se você decidir implementar a autenticação por conta própria, em vez de usar um serviço ou outra biblioteca, é essencial entender que a maneira como você protege as senhas pode afetar diretamente a segurança geral da sua aplicação.
Introdução ao Bcrypt para hashing de senhas no Node.js
Bcrypt é um algoritmo e pacote npm que oferece uma função de hashing de senhas considerada muito segura. Ele incorpora um salt (dados aleatórios) para proteger contra ataques de rainbow table e permite configurar o fator de custo, que determina o uso de CPU necessário para o hashing — um recurso útil para evitar ataques de força bruta.
Vamos ver um caso de uso simples:
O parâmetro saltRounds determina a complexidade do processo de hashing. Quanto maior o valor, mais tempo o processo leva, o que pode ajudar a proteger contra ataques de força bruta. A função hash adiciona um salt e gera automaticamente o hash da senha em texto simples. Depois, você pode armazenar o hash resultante no banco de dados.
Perguntas frequentes sobre hashing de senhas e gerenciamento de autenticação no Node.js
Qual é um bom tamanho de salt para usar com Bcrypt?
O Bcrypt gera automaticamente um salt de 16 bytes.
Com que frequência devo atualizar meu algoritmo ou estratégia de hash?
Se houver um avanço significativo na tecnologia de hash ou for descoberta uma vulnerabilidade no algoritmo que você usa, é recomendável atualizar sua estratégia de hash. O Node.js oferece suporte integrado ao algoritmo scrypt como parte do módulo principal node:crypto.
O que é o fator de custo no Bcrypt?
O fator de custo determina o quanto o processo de hash exige da CPU. Quanto maior o fator, mais seguro será o hash, mas também levará mais tempo para ser calculado. No Node.js, isso também pode afetar diretamente o event loop e a capacidade de resposta da sua aplicação, dependendo de como o hash é gerado.
4. Evite ataques de injeção de SQL com Knex.js
A injeção de SQL é uma vulnerabilidade de segurança comum que representa um risco significativo para os dados das aplicações. Desenvolvedores Node.js podem reduzir esse risco usando o Knex.js, um construtor de consultas SQL promissor, para criar consultas mais seguras. No entanto, lembre-se de que o Knex.js também permite criar e executar consultas SQL brutas. Nesse caso, a injeção de SQL continua sendo um problema de segurança, pois pode ocorrer ao concatenar entradas de usuários na consulta.
Knex.js é um poderoso construtor de consultas SQL para Node.js. Ele oferece suporte a transações, agrupamento de conexões, migrações e seeds, sendo uma opção preferida por desenvolvedores que querem escrever consultas SQL seguras, robustas e escaláveis. O Knex.js ajuda a evitar ataques de injeção de SQL usando consultas parametrizadas e escapando os valores inseridos nas instruções SQL.
Veja este trecho de código que demonstra como o Knex.js protege contra ataques de injeção de SQL:
Neste exemplo, o Knex.js escapa automaticamente o valor de userProvidedValue, evitando possíveis ataques de injeção de SQL.
Como dissemos antes, usar o Knex.js por si só não é uma proteção completa nem uma solução isolada contra injeção de SQL. Veja um exemplo de uso potencialmente inseguro do Knex.js que pode levar a um ataque de injeção de SQL:
Nesse caso, o valor de userProvidedValue não é escapado nem parametrizado, deixando a consulta vulnerável a injeção de SQL se userProvidedValue contiver código SQL malicioso. O Snyk pode ajudar desenvolvedores a detectar esse tipo de vulnerabilidade na base de código. O Snyk analisa seu código e oferece insights práticos para corrigir vulnerabilidades de segurança, incluindo possíveis ataques de injeção de SQL.
Encontre e corrija vulnerabilidades em JavaScript
Proteja suas aplicações com a análise de vulnerabilidades e as recomendações de correção da Snyk.
Não é necessário informar cartão de crédito.
Ou cadastre-se com Azure AD Docker ID Bitbucket
Ao usar a Snyk, você concorda em cumprir nossas políticas, incluindo os Termos de Serviço e a Política de Privacidade.
Perguntas frequentes sobre como evitar injeção de SQL com Knex.js
O que é uma injeção de SQL?
Injeção de SQL é uma técnica em que um invasor insere código SQL malicioso em uma consulta. Essa invasão pode levar ao acesso não autorizado a dados confidenciais, à corrupção de dados ou até mesmo à perda de dados. Por isso, prevenir ataques de injeção de SQL é essencial para a segurança das aplicações.
O Knex.js é imune a ataques de injeção de SQL?
Embora o Knex.js ajude muito a reduzir os riscos de injeção de SQL com consultas parametrizadas e escape de valores, ele não é totalmente imune. Os desenvolvedores precisam garantir que estão usando o Knex.js corretamente e não introduzindo vulnerabilidades.
Usar Knex.js é suficiente para prevenir injeções de SQL?
Embora o Knex.js seja uma ferramenta poderosa para prevenir injeções de SQL, ele não é uma solução completa por si só. Os desenvolvedores também devem adotar outras boas práticas de segurança, como validar as entradas e aplicar o princípio do menor privilégio.
5. Implemente a limitação de taxa com fastify-rate-limit
A limitação de taxa é um mecanismo de segurança essencial para proteger suas aplicações web contra ataques de negação de serviço (DoS). Ao controlar o número de solicitações que um cliente pode fazer à sua aplicação em um determinado período, você evita que clientes mal-intencionados sobrecarreguem seu servidor com muitas solicitações e garante que a aplicação continue disponível para os demais usuários legítimos.
fastify-rate-limit é um plugin para o framework web Fastify que oferece uma interface fácil de usar para implementar a limitação de taxa nas suas aplicações Node.js. Com ele, você define o número máximo de solicitações que um cliente pode fazer em um determinado período e a resposta a ser enviada quando esse limite for ultrapassado.
Veja um exemplo básico de como implementar a limitação de taxa na sua aplicação Node.js usando fastify-rate-limit:
Neste trecho de código, o pacote de limitação de taxa do Fastify é configurado para limitar cada cliente a 100 solicitações por minuto. Se um cliente ultrapassar esse limite, o servidor responderá com o código de status 429 ("Muitas solicitações").
Perguntas frequentes sobre limitação de taxa
A limitação de taxa pode afetar o desempenho do meu aplicativo?
Não. A limitação de taxa melhora o desempenho e a disponibilidade do seu aplicativo ao evitar que ele fique sobrecarregado com um grande número de solicitações.
O que devo fazer se um usuário legítimo ultrapassar o limite de requisições?
Dependendo das necessidades da sua aplicação, você pode aumentar o limite de requisições, excluir determinados endereços IP da limitação ou implementar uma estratégia mais sofisticada que leve em conta o comportamento e a reputação do usuário.
A limitação de taxa pode impedir todos os tipos de ataques de negação de serviço (DoS)?
A limitação de taxa é eficaz contra ataques de DoS que tentam sobrecarregar seu servidor com um grande número de solicitações. No entanto, ela não protege contra outros tipos de ataques de DoS que exploram vulnerabilidades específicas no seu aplicativo ou servidor. Por isso, é importante implementar uma estratégia de segurança abrangente, que inclua a limitação de taxa e outras medidas de segurança.
Por que desenvolvedores devem usar o Snyk para proteger JavaScript
Neste artigo, abordamos cinco trechos essenciais de código de segurança em Node.js que todo desenvolvedor backend deve conhecer. Falamos sobre a importância de práticas de codificação segura, como evitar injeção de SQL, e o papel fundamental delas no aumento da segurança das aplicações. Com a evolução da tecnologia e a crescente complexidade das ameaças cibernéticas, nunca é demais reforçar a importância de escrever código seguro.
Como desenvolvedor, é fundamental usar ferramentas de segurança robustas que ajudem a identificar e reduzir possíveis vulnerabilidades no seu código. Uma dessas ferramentas é o Snyk, uma poderosa plataforma de segurança para desenvolvedores que permite detectar e corrigir vulnerabilidades no código, nas dependências, nos contêineres e muito mais. Com o Snyk, você monitora continuamente sua aplicação em busca de vulnerabilidades de segurança e recebe PRs de correção automáticas quando uma nova vulnerabilidade é descoberta.
O Snyk se integra perfeitamente aos seus ambientes de desenvolvimento integrados (IDEs) e ao seu pipeline de CI/CD, ajudando você a manter a segurança contínua em todo o ciclo de desenvolvimento da aplicação. A plataforma oferece suporte a diversas linguagens de programação, incluindo Node.js, sendo uma ferramenta versátil para desenvolvedores que trabalham em diferentes plataformas.
Escrever código seguro é uma prática fundamental no desenvolvimento de software e deve ser prioridade para todo desenvolvedor backend. O uso de ferramentas de segurança como o Snyk reforça essa prática ao detectar e ajudar a corrigir vulnerabilidades automaticamente. À medida que enfrentamos um cenário de ameaças cibernéticas em constante evolução, essas práticas e ferramentas serão essenciais para manter a segurança e a integridade das nossas aplicações.
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.



