Segurança de Aplicações JavaScript: Top 10 Vulnerabilidades
JavaScript, especialmente no ambiente Node.js, tornou-se a base do desenvolvimento web moderno. No entanto, sua popularidade torna as aplicações um alvo atraente para ataques. Ignorar questões de segurança pode levar a vazamento de dados, perdas financeiras e danos à reputação. Neste artigo, analisaremos as 10 vulnerabilidades mais críticas de aplicações JavaScript (Node.js), baseadas no padrão OWASP Top 10, e mostraremos como preveni-las com exemplos de código.
1. Injeção (Injection)
Injeções continuam sendo uma das ameaças mais perigosas. No contexto do Node.js, as mais comuns são SQL injection e NoSQL injection (por exemplo, no MongoDB).
Problema
A concatenação direta da entrada do usuário em consultas ao banco de dados permite que um invasor execute código arbitrário.
Exemplo de código vulnerável
const user = req.body.username;const query = `SELECT * FROM users WHERE username = '${user}'`;db.query(query, callback);Solução
Use consultas parametrizadas ou ORM/ODM. Para MongoDB, utilize mongo-sanitize.
const query = 'SELECT * FROM users WHERE username = $1';db.query(query, [user], callback);2. Falha na Autenticação e Gerenciamento de Sessões
Autenticação fraca é um caminho direto para o comprometimento de contas.
Problema
Uso de tokens previsíveis (por exemplo, JWT com algoritmo none), armazenamento de senhas em texto puro ou ausência de limite no número de tentativas de login.
Exemplo de vulnerabilidade
// JWT sem verificação de algoritmoconst token = jwt.sign({ user: 'admin' }, 'secret', { algorithm: 'none' });Solução
- Sempre verifique o algoritmo JWT:
jwt.verify(token, secret, { algorithms: ['HS256'] }). - Armazene senhas usando
bcryptouargon2. - Implemente limite de tentativas de login (
express-rate-limit).
const bcrypt = require('bcrypt');const saltRounds = 10;const hash = await bcrypt.hash(password, saltRounds);3. XSS (Cross-Site Scripting)
XSS permite injetar um script malicioso em uma página web, que é então executado no navegador da vítima.
Problema
Exibição de conteúdo do usuário sem escape, especialmente ao usar Server-Side Rendering (SSR) no Next.js ou Nuxt.js.
Código vulnerável (Express)
res.send(`<h1>Hello, ${req.query.name}</h1>`);Solução
- Escape a saída: use bibliotecas como
escape-htmlou template engines com auto-escape (EJS, Pug). - Defina o cabeçalho CSP (Content Security Policy):
helmet.contentSecurityPolicy().
const helmet = require('helmet');app.use(helmet.contentSecurityPolicy({ directives: { defaultSrc: ["'self'"] }}));4. Referência Direta Insegura a Objetos (IDOR)
A vulnerabilidade ocorre quando um usuário pode acessar objetos (arquivos, registros de BD) conhecendo ou adivinhando seu identificador.
Exemplo
app.get('/api/user/:id', (req, res) => { // Não há verificação se req.user.id === req.params.id const user = db.findUser(req.params.id); res.json(user);});Solução
Sempre verifique as permissões de acesso no nível do servidor.
if (req.user.id !== req.params.id) { return res.status(403).send('Forbidden');}5. Configuração de Segurança Incorreta
Isso inclui o uso de credenciais padrão, modos de depuração em produção e configurações incorretas de CORS.
Problema
// CORS abertoapp.use(cors({ origin: '*' }));