Segurança de aplicações web no Brasil: OWASP Top 10, autenticação JWT, LGPD técnica e pentest para sistemas empresariais
Guia técnico de segurança web para empresas brasileiras: OWASP Top 10 atualizado, JWT seguro, requisitos técnicos da LGPD, headers e pentest.
Toda empresa brasileira que tem um sistema web é um alvo
Em 2025, o Brasil foi o segundo país mais atacado por ciberataques na América Latina, com mais de 100 bilhões de tentativas de ataque registradas. E o alvo mais comum não são os grandes bancos (que investem bilhões em segurança) — são as aplicações web corporativas: ERPs, CRMs, portais de clientes, sistemas de RH, plataformas de e-commerce.
Os motivos são previsíveis: empresas de médio porte raramente têm equipe dedicada de segurança, sistemas legados nunca passaram por pentest, e a LGPD (Lei Geral de Proteção de Dados) transformou vazamento de dados de "problema técnico" em "problema jurídico com multa de até 2% do faturamento".
Esse post é o guia técnico completo para proteger aplicações web no contexto brasileiro: OWASP Top 10 aplicado à realidade de sistemas empresariais, autenticação JWT feita corretamente, requisitos técnicos da LGPD que afetam o código, security headers que todo sistema deveria ter, e quando e como fazer pentest.
OWASP Top 10 (2021): o que significa para sistemas empresariais brasileiros
O OWASP Top 10 é a referência global de vulnerabilidades em aplicações web. A lista de 2021 (ainda vigente em 2026) reorganizou categorias com foco em causas raiz:
A01 — Broken Access Control (Controle de Acesso Quebrado)
O que é: usuário consegue acessar recursos que não deveria — ver dados de outro cliente, acessar painel administrativo, editar registro de outro usuário.
Exemplo real em ERP: vendedor acessa a tela de comissões e, alterando o ID na URL (/api/comissoes/vendedor/42 → /api/comissoes/vendedor/43), vê as comissões de outro vendedor. Isso é IDOR (Insecure Direct Object Reference).
Como prevenir:
// ERRADO - confia no ID da URL
GET /api/pedidos/:pedidoId
→ Retorna pedido independente de quem está logado
// CORRETO - valida ownership
GET /api/pedidos/:pedidoId
→ Verifica se pedido pertence ao usuário/empresa logada
→ Nega acesso com 403 se não pertence
Regras:
- Deny by default: negar acesso e liberar explicitamente, nunca o contrário
- Validar no backend: nunca confiar em controle de acesso no frontend
- Row-level security: filtrar dados por tenant/empresa/usuário em toda query
- Logs de acesso negado: cada tentativa de acesso negado deve gerar log com IP, usuário e recurso
A02 — Cryptographic Failures (Falhas Criptográficas)
O que é: dados sensíveis transmitidos ou armazenados sem criptografia adequada.
Exemplos no contexto brasileiro:
- Senha armazenada em MD5 ou SHA-1 (ambos quebrados)
- CPF armazenado em texto puro no banco
- API interna trafegando dados pessoais via HTTP (não HTTPS)
- Certificado digital A1 armazenado no servidor sem proteção
Como prevenir:
- Senhas: bcrypt ou Argon2id com salt, nunca MD5/SHA-1/SHA-256 sem salt
- Dados pessoais em repouso: AES-256 para campos sensíveis (CPF, dados bancários)
- Dados em trânsito: TLS 1.2+ obrigatório, TLS 1.3 preferível
- Certificados digitais: armazenar em vault (HashiCorp Vault, Azure Key Vault, AWS Secrets Manager)
- Chaves de API: nunca no código-fonte, sempre em variáveis de ambiente ou vault
A03 — Injection (Injeção)
O que é: dados fornecidos pelo usuário são interpretados como código (SQL, NoSQL, OS command, LDAP).
SQL Injection em sistema fiscal (cenário real):
// VULNERÁVEL
const query = `SELECT * FROM notas_fiscais
WHERE numero = '${req.params.numero}'`;
// Atacante envia: ' OR '1'='1' --
// Query resultante:
// SELECT * FROM notas_fiscais WHERE numero = '' OR '1'='1' --'
// Retorna TODAS as notas fiscais do sistema
// CORRETO - prepared statement
const query = `SELECT * FROM notas_fiscais WHERE numero = $1`;
const result = await db.query(query, [req.params.numero]);
Regras:
- Sempre usar prepared statements/parameterized queries
- Validar e sanitizar input: tipo, tamanho, formato esperado
- Princípio do menor privilégio no banco: a conexão da aplicação não deve ter permissão de DROP, CREATE, ALTER
- WAF (Web Application Firewall): camada adicional que filtra payloads maliciosos
A04 — Insecure Design (Design Inseguro)
O que é: a vulnerabilidade está no design do sistema, não na implementação. Exemplo: sistema de recuperação de senha que pergunta "qual o nome do seu pet" — a resposta pode ser encontrada nas redes sociais.
No contexto empresarial: sistema de aprovação de pedidos que permite que o mesmo usuário solicite e aprove um pedido acima de R$ 100k. O código pode estar perfeito, mas o design é inseguro (falta segregação de funções).
Como prevenir:
- Threat modeling antes de implementar features críticas
- Segregação de funções (quem solicita não aprova)
- Limites por nível de acesso (estagiário não pode gerar NF-e acima de X)
- Revisão de design por pessoa diferente do implementador
A05 a A10 — Visão rápida
| # | Vulnerabilidade | Exemplo em sistema empresarial |
|---|---|---|
| A05 | Security Misconfiguration | Debug mode ativo em produção, stack trace exposto na API |
| A06 | Vulnerable Components | Biblioteca npm com CVE conhecida não atualizada |
| A07 | Authentication Failures | Login sem rate limiting, brute force possível |
| A08 | Data Integrity Failures | CI/CD pipeline sem verificação de integridade de dependências |
| A09 | Logging/Monitoring Failures | Ataque em andamento sem nenhum alerta |
| A10 | SSRF | API interna que aceita URL externa como parâmetro |
Autenticação JWT: como fazer certo (e os erros que todo mundo comete)
JWT (JSON Web Token) é o padrão de autenticação mais usado em APIs e SPAs (Single Page Applications). Mas a quantidade de implementações inseguras no mercado é assustadora.
Como JWT funciona
┌──────────────────────────────────────────────┐
│ JWT Token │
│ │
│ Header.Payload.Signature │
│ │
│ Header: │
│ {"alg": "RS256", "typ": "JWT"} │
│ │
│ Payload: │
│ { │
│ "sub": "user-123", │
│ "email": "user@empresa.com", │
│ "role": "admin", │
│ "tenant": "empresa-abc", │
│ "iat": 1717459200, │
│ "exp": 1717462800 │
│ } │
│ │
│ Signature: │
│ RS256(base64(header) + "." + │
│ base64(payload), privateKey) │
└──────────────────────────────────────────────┘
Os 7 erros mais comuns em JWT
1. Usar algoritmo "none"
Algumas bibliotecas JWT aceitam "alg": "none", que significa "sem assinatura". Atacante pode forjar qualquer token.
Solução: validar explicitamente o algoritmo esperado no backend. Rejeitar qualquer token que não use o algoritmo configurado.
2. Usar HMAC (HS256) com chave fraca
HS256 usa chave simétrica. Se a chave é "secret123", qualquer pessoa que descubra pode forjar tokens.
Solução: usar RS256 (chave assimétrica) ou HS256 com chave de pelo menos 256 bits gerada aleatoriamente.
3. Token com validade muito longa
Token de acesso com validade de 30 dias é um convite para roubo de sessão.
Solução:
- Access token: 15 a 60 minutos de validade
- Refresh token: 7 a 30 dias, armazenado em httpOnly cookie
- Refresh token rotation: cada uso do refresh token gera um novo (o anterior é invalidado)
4. Armazenar token em localStorage
localStorage é acessível por qualquer JavaScript na página. Um XSS rouba o token.
Solução: armazenar em httpOnly cookie com flags Secure, SameSite=Strict. O JavaScript da aplicação não consegue acessar, mas o cookie é enviado automaticamente em cada request.
5. Não validar claims no backend
Token contém "role": "admin" — mas o backend confia cegamente sem verificar no banco se o usuário realmente é admin.
Solução: claims no JWT são para performance (evitar consulta ao banco a cada request), mas operações críticas devem revalidar permissões no banco.
6. Não implementar revogação
JWT é stateless — não tem como "invalidar" um token emitido. Se um funcionário é demitido, o token dele continua válido até expirar.
Solução:
- Manter blocklist de tokens revogados em Redis (com TTL igual à expiração do token)
- Ou manter versão do token no banco do usuário — incrementar a versão invalida todos os tokens anteriores
7. Expor dados sensíveis no payload
JWT payload é apenas encodado em base64, não é criptografado. Qualquer pessoa pode decodificar e ler o conteúdo.
Solução: nunca colocar dados sensíveis (senha, CPF completo, dados bancários) no payload. Apenas identificadores (user ID, tenant ID, role).
Implementação segura de autenticação
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ Login │────→│ Auth Server │────→│ Banco/LDAP │
│ (email │ │ Valida creds │ │ Verifica │
│ +senha) │ │ Gera JWT │ │ senha hash │
└──────────┘ └──────┬───────┘ └──────────────┘
│
↓
┌──────────────────┐
│ Retorna: │
│ - Access token │
│ (JWT, 30min) │
│ - Refresh token │
│ (httpOnly cookie│
│ 30 dias) │
│ - CSRF token │
└──────────────────┘
│
↓
┌──────────────────┐
│ Requests seguintes│
│ Authorization: │
│ Bearer <token> │
│ Cookie: refresh= │
└──────────────────┘
LGPD: requisitos técnicos que afetam o código
A LGPD (Lei 13.709/2018) não é apenas um problema jurídico. Ela impõe requisitos técnicos que afetam diretamente a arquitetura e o código do sistema.
Bases legais que o sistema precisa registrar
Cada dado pessoal coletado precisa ter uma base legal registrada:
- Consentimento (art. 7, I): usuário autorizou explicitamente
- Obrigação legal (art. 7, II): ex: dados de colaboradores para eSocial
- Execução de contrato (art. 7, V): dados necessários para prestar o serviço contratado
- Legítimo interesse (art. 7, IX): interesse do controlador, com teste de proporcionalidade
O sistema deve registrar: qual dado, de quem, com qual base legal, quando foi coletado, por quanto tempo será retido.
Direitos do titular — o que o sistema precisa implementar
A LGPD garante ao titular (pessoa cujos dados são tratados) 9 direitos que o sistema precisa suportar tecnicamente:
1. Confirmação de existência e acesso (art. 18, I e II)
O sistema deve ser capaz de gerar um relatório completo de todos os dados pessoais de um titular. Isso significa:
- Mapear todas as tabelas que contêm dados pessoais
- Criar query que cruza por CPF/e-mail e retorna tudo
- Gerar relatório em formato legível
2. Correção (art. 18, III)
Titular pode solicitar correção de dados incorretos. O sistema deve permitir edição com log de auditoria (dado anterior e novo, quem alterou, quando).
3. Anonimização, bloqueio ou eliminação (art. 18, IV)
O mais complexo tecnicamente. O sistema deve ser capaz de:
- Anonimizar: substituir dados pessoais por dados irreversíveis (hash sem possibilidade de reversão, remoção de campos identificadores)
- Eliminar: apagar dados pessoais sem apagar registros transacionais que dependem deles
O problema: uma NF-e emitida para CPF 123.456.789-00 é um documento fiscal que deve ser guardado por 5 anos. Não pode apagar. Mas o titular pediu eliminação. A solução é anonimizar os dados pessoais no cadastro mas manter a referência fiscal (NF-e em si é obrigação legal).
4. Portabilidade (art. 18, V)
Titular pode pedir seus dados em formato interoperável. O sistema deve exportar em JSON, CSV ou XML.
Implementação técnica de consentimento
┌─────────────────────────────────────────┐
│ Tabela: consents │
│ │
│ id UUID │
│ user_id UUID (FK → users) │
│ purpose VARCHAR (finalidade) │
│ legal_basis ENUM (consent, contract, │
│ legal_obligation, ...) │
│ granted_at TIMESTAMP │
│ revoked_at TIMESTAMP (nullable) │
│ ip_address INET │
│ user_agent TEXT │
│ version INT (versão do termo) │
│ evidence TEXT (hash do termo aceito)│
└─────────────────────────────────────────┘
Cada consentimento deve ser:
- Granular: consentimento para marketing é separado de consentimento para analytics
- Revogável: o titular pode revogar a qualquer momento, com efeito imediato
- Versionado: se o termo de uso muda, novo consentimento é necessário
- Com evidência: registro de quando, como e qual versão do termo foi aceita
Retenção e descarte de dados
O sistema deve implementar política de retenção por tipo de dado:
| Tipo de dado | Prazo de retenção | Base legal |
|---|---|---|
| Dados de colaboradores (CLT) | 5 anos após desligamento | Prescrição trabalhista |
| Notas fiscais | 5 anos | Obrigação fiscal |
| Dados de clientes PF | Enquanto durar a relação + 5 anos | Execução de contrato + prescrição |
| Logs de acesso | 6 meses (Marco Civil) | Obrigação legal |
| Dados de candidatos (R&S) | 6-12 meses após processo seletivo | Legítimo interesse |
| Dados de marketing | Enquanto houver consentimento | Consentimento |
Job automatizado deve identificar dados que ultrapassaram o prazo e executar anonimização/eliminação.
Security Headers: configuração obrigatória
Headers HTTP de segurança que toda aplicação web deve implementar:
# Previne XSS refletido (browsers modernos)
Content-Security-Policy: default-src 'self';
script-src 'self'; style-src 'self' 'unsafe-inline';
img-src 'self' data:; font-src 'self';
connect-src 'self' https://api.empresa.com;
frame-ancestors 'none'
# Previne clickjacking
X-Frame-Options: DENY
# Previne MIME type sniffing
X-Content-Type-Options: nosniff
# Controla informação enviada no Referer
Referrer-Policy: strict-origin-when-cross-origin
# Força HTTPS por 1 ano
Strict-Transport-Security: max-age=31536000;
includeSubDomains; preload
# Controla features do browser
Permissions-Policy: camera=(), microphone=(),
geolocation=(), payment=()
Como verificar
Ferramentas para auditar headers:
- securityheaders.com: nota de A a F
- Mozilla Observatory: análise completa
- curl -I: verificação manual rápida
A Bradata implementa security headers como configuração padrão em todas as aplicações que desenvolve, com Content-Security-Policy configurada por ambiente (dev mais permissivo, produção restritivo).
Pentest: quando, como e o que testar
Pentest (teste de penetração) é a validação prática da segurança — um profissional tenta invadir o sistema usando as mesmas técnicas que um atacante real.
Tipos de pentest
Black box: testador não recebe nenhuma informação sobre o sistema. Simula atacante externo.
Gray box: testador recebe credenciais de usuário comum e documentação básica. Simula funcionário malicioso ou credencial vazada.
White box: testador recebe acesso ao código-fonte, arquitetura e credenciais. Análise mais profunda, encontra mais vulnerabilidades.
Para sistemas empresariais, gray box é o mais custo-efetivo: testa tanto ataques externos quanto escalação de privilégios internos.
O que testar em um sistema empresarial brasileiro
Checklist específico para o contexto:
Autenticação e autorização:
- Brute force no login (rate limiting funciona?)
- Escalação horizontal (usuário A acessa dados do usuário B)
- Escalação vertical (usuário normal acessa funções de admin)
- Bypass de 2FA (se implementado)
- Session fixation e session hijacking
Dados fiscais:
- Acesso não autorizado a NF-es de outras empresas (multi-tenant)
- Manipulação de valores em XML de NF-e antes da assinatura
- Acesso a certificado digital armazenado no servidor
Dados pessoais (LGPD):
- Exportação massiva de dados pessoais sem autorização
- SQL injection em campos de busca de clientes/funcionários
- Dados pessoais em logs de aplicação
- Dados pessoais em URLs (GET parameters)
Infraestrutura:
- Portas abertas desnecessariamente
- Serviços expostos (Redis, Elasticsearch, banco de dados)
- Versões desatualizadas de software com CVEs conhecidas
- Secrets em repositório de código (API keys, senhas)
Frequência recomendada
- Pentest completo: anual (ou após mudanças arquiteturais significativas)
- Scan automatizado (DAST): mensal (ferramentas como OWASP ZAP, Burp Suite)
- SAST (análise de código estático): integrado no CI/CD (SonarQube, Snyk, Semgrep)
- Dependency scanning: contínuo (Dependabot, Snyk, npm audit)
Resposta a incidentes: o que fazer quando der errado
A LGPD exige notificação à ANPD (Autoridade Nacional de Proteção de Dados) em prazo razoável (a ANPD recomenda 2 dias úteis) quando houver incidente de segurança que possa acarretar risco ou dano relevante aos titulares.
Plano de resposta a incidentes (mínimo)
1. DETECÇÃO
- Alerta de monitoramento (SIEM, WAF, IDS)
- Ou denúncia interna/externa
2. CONTENÇÃO (primeiras 4 horas)
- Isolar sistema afetado
- Preservar evidências (logs, snapshots)
- Comunicar time de resposta
3. ANÁLISE (primeiras 24 horas)
- Identificar escopo (quais dados, quantos titulares)
- Identificar vetor de ataque
- Avaliar risco aos titulares
4. NOTIFICAÇÃO (48 horas)
- ANPD (se risco relevante)
- Titulares afetados (se risco relevante)
- Encarregado de dados (DPO)
5. REMEDIAÇÃO
- Corrigir vulnerabilidade
- Atualizar controles
- Documentar lições aprendidas
O que logar para ter evidência
O sistema deve registrar:
- Tentativas de login (sucesso e falha) com IP e user-agent
- Acessos a dados pessoais (quem, quando, qual dado)
- Alterações em permissões (quem deu/removeu acesso)
- Exportações de dados (quem exportou, quanto, quando)
- Erros de autorização (tentativa de acesso negada)
Logs devem ser armazenados em local separado da aplicação (serviço centralizado de logs), com retenção mínima de 6 meses (Marco Civil da Internet) e proteção contra adulteração.
Checklist de segurança para aplicações web brasileiras
Lista consolidada para revisão antes de ir para produção:
Infraestrutura
- HTTPS obrigatório com TLS 1.2+ (certificado válido)
- Security headers configurados (CSP, HSTS, X-Frame-Options)
- WAF ativo (Cloudflare, AWS WAF, Azure Front Door)
- Banco de dados não acessível pela internet
- Secrets em vault, não em código ou variáveis de ambiente expostas
- Backups criptografados com teste de restore periódico
Aplicação
- Prepared statements em todas as queries SQL
- Validação de input em todas as entradas (tipo, tamanho, formato)
- Output encoding para prevenção de XSS
- Rate limiting em endpoints de autenticação
- Controle de acesso validado no backend (não apenas frontend)
- Row-level security em aplicações multi-tenant
- Senhas com bcrypt/Argon2id, nunca MD5/SHA
Autenticação
- JWT com RS256 e validade curta (15-60 min)
- Refresh token em httpOnly cookie com rotation
- Blocklist de tokens revogados
- MFA disponível para administradores
- Política de senha (mínimo 12 caracteres, sem requisitos de complexidade arbitrários)
LGPD
- Mapeamento de dados pessoais documentado
- Base legal registrada para cada tratamento
- Mecanismo de consentimento granular e revogável
- Endpoint para exercício de direitos do titular
- Política de retenção implementada com job de descarte
- Registro de atividades de tratamento
Monitoramento
- Logs centralizados com retenção de 6+ meses
- Alertas para tentativas de acesso não autorizado
- Dashboard de saúde de segurança
- Scan de vulnerabilidades automatizado no CI/CD
- Plano de resposta a incidentes documentado e testado
A Bradata aplica esse checklist em todos os sistemas que desenvolve, com validação automatizada no pipeline de CI/CD e revisão manual antes de cada release em produção.
Conclusão: segurança não é feature, é fundação
Segurança de aplicações web no Brasil envolve uma combinação de desafios técnicos (OWASP Top 10, autenticação, criptografia) com desafios regulatórios (LGPD, Marco Civil, regulamentações setoriais). Tratar segurança como algo que se adiciona depois — "vamos lançar e depois fazemos pentest" — é a receita para vazamentos, multas e perda de confiança.
O caminho é integrar segurança no processo de desenvolvimento desde o início: threat modeling no design, SAST no CI/CD, security headers no deploy, pentest periódico em produção. É mais barato prevenir do que remediar — e no cenário regulatório brasileiro atual, remediar pode significar multa de R$ 50 milhões ou 2% do faturamento.
Posts relacionados
Automação de marketing para empresas brasileiras: fluxos, lead scoring, landing pages e LGPD
BNCC, Censo Escolar e LGPD na escola em 2026: o que muda para gestores e qual o checklist de tecnologia
LGPD na saúde em 2026: prontuário eletrônico, telemedicina e o checklist técnico definitivo para clínicas e hospitais
Precisa de um talento tech agora?
Fale com a Bradata e receba uma proposta em 24 horas úteis.