Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

Auditoria de Segurança – CRMFoda

Este documento lista as principais vulnerabilidades e riscos de segurança identificados no backend (NestJS), frontend (Angular) e serviços auxiliares deste projeto, com base na análise do código-fonte presente no repositório.


Visão Geral

  • Stack backend: NestJS, Knex, PostgreSQL, JWT, WebSockets, integrações com WhatsApp (Uazapi e Meta), N8N, Supabase S3.
  • Stack frontend: Angular 21, SPA com autenticação via JWT armazenado no localStorage.
  • Modelo de segurança esperado: autenticação por JWT, multi-tenant por account_id, rate limiting global via ThrottlerModule, webhooks autenticados por secrets.

Estrutura de Repositórios / Projetos

  • Estado atual:
    • O backend (backend/), o frontend (frontend/) e o webhook proxy (webhook-proxy/) estão no mesmo repositório (monorepo).
  • Recomendação de separação de repositórios:
    • Backend (NestJS):
      • Criar um repositório dedicado apenas para o serviço de API/worker (código atual de backend/), com seu próprio ciclo de CI/CD, versionamento e hardening.
    • Frontend (Angular):
      • Criar um repositório separado para o SPA (código atual de frontend/), isolando dependências de build frontend e pipeline de deploy estático.
    • Webhook Proxy (Cloudflare Worker):
      • Manter o código de webhook-proxy/ em um terceiro repositório, focado apenas no worker de proxy de webhooks (KV, tenants, rotas /webhook e /tenants).
    • Essa separação permite:
      • Isolar superfícies de ataque (cada serviço com permissões mínimas necessárias).
      • Aplicar políticas de segurança, revisão de código e deploy independentes para backend, frontend e proxy de webhooks.

Apesar de existirem boas práticas (uso de helmet, CORS restritivo em produção, secrets em variáveis de ambiente, rate limiting), há vulnerabilidades graves que permitem:

  • Escalada de privilégios
  • Acesso ou modificação indevida de dados de outros tenants
  • Comprometimento total do sistema em caso de vazamento de uma única chave
  • Exposição de senhas em texto claro no banco de dados

Checklist por Tipo de Vulnerabilidade

1. Falhas de Autenticação e Autorização

  • Encontrado (Crítico):
    • Endpoints de WhatsApp (/whatsapp/*) totalmente sem autenticação, permitindo operações sensíveis usando apenas username.
    • API de permissões (/permissions/:userId) sem controle de papel, permitindo que qualquer usuário autenticado altere permissões de qualquer outro.
    • Chave de API global (API_KEY) que gera um “usuário” com role: 'admin' e is_super_admin: true, usada em JwtOrApiKeyGuard.
    • Usuário especial username === 'dev' em PermissionsService com poderes de super admin implícitos sobre boards.
  • Bom/OK:
    • Fluxo de login usa AuthGuard('local') + bcrypt + JWT com expiração.
    • Estratégia JWT valida se o usuário está ativo.
  • Ações recomendadas:
    • Colocar @UseGuards(AuthGuard('jwt')) (ou guard específico) em todos os endpoints que hoje dependem apenas de username.
    • Centralizar verificação de papel/escopo em um guard ou decorator (RolesGuard) e aplicá-lo a rotas administrativas.
    • Remover ou limitar fortemente o “usuário dev” e a chave API_KEY global, adotando chaves escopadas e auditadas.

2. Injeção de Código (SQL / NoSQL / Command Injection)

  • SQL Injection:
    • O backend usa Knex com bindings em praticamente todos os pontos; onde há raw, os parâmetros vêm de constantes ou bindings seguros.
    • Campos de busca (search em estatísticas e cards) usam .whereILike com interpolação aplicada antes da query, fazendo com que Knex trate como parâmetro.
    • Não há uso direto de strings concatenadas em whereRaw com input do usuário.
  • NoSQL / Command Injection:
    • Não há uso de ORMs NoSQL nem de child_process, eval, Function, exec, spawn no backend.
  • Conclusão:
    • Nenhum vetor óbvio de SQL/NoSQL/Command Injection foi identificado na análise estática.
    • Risco residual depende da correta configuração da conexão e de futuros raw(); recomenda‑se manter a regra de nunca concatenar input de usuário em SQL cru.

3. Cross-Site Scripting (XSS)

  • Frontend (Angular):
    • Não há uso de innerHTML, DomSanitizer.bypassSecurityTrustHtml ou padrões semelhantes.
    • As páginas usam binding Angular padrão ({{ }} e property binding), que já escapam HTML por padrão.
  • Backend:
    • API é JSON, sem construção manual de HTML a partir de input do usuário.
  • Vetores indiretos:
    • Conteúdos provenientes de contatos/mensagens podem conter texto arbitrário; se no futuro forem renderizados como HTML (por ex. via [innerHTML]), poderão abrir XSS armazenado.
    • O uso de localStorage para JWT aumenta o impacto de um XSS, mesmo que hoje não haja vetores óbvios.
  • Conclusão:
    • Não foi identificado XSS direto no código atual, mas qualquer mudança futura que introduza innerHTML ou renderização de HTML vindo do backend deve ser cuidadosamente auditada.

4. Cross-Site Request Forgery (CSRF)

  • Situação atual:
    • A autenticação é feita por JWT em header Authorization: Bearer, não por cookies.
    • Não há uso de cookies de sessão nem de CSRF tokens no backend.
  • Impacto:
    • Com o modelo atual (sem cookies de autenticação), o risco de CSRF clássico é baixo.
    • Se no futuro o JWT for movido para cookie HttpOnly (recomendado para proteção contra XSS), será necessário adicionar proteção CSRF (tokens, SameSite adequado, etc.).
  • Conclusão:
    • Não há CSRF clássico hoje devido ao modelo de autenticação, mas o tema deve ser revisitado se o mecanismo de sessão mudar.

5. Falhas de Configuração de Segurança

  • Positivas:
    • Uso de helmet com vários headers de segurança ativados.
    • contentSecurityPolicy desativado apenas em dev; em produção segue o default do Helmet.
    • CORS_ORIGIN='*' é explicitamente bloqueado em produção.
    • ThrottlerModule configurado globalmente com três buckets (short, medium, long).
    • Webhooks N8N e Meta validados via secretos (N8N_WEBHOOK_SECRET, META_WHATSAPP_VERIFY_TOKEN, META_APP_SECRET).
  • Problemas:
    • Ausência de ValidationPipe global – qualquer payload passa sem validação estruturada.
    • @SkipThrottle() aplicado em webhooks, deixando-os sem rate limit em nível de aplicação.
    • Websocket gateway com CORS dependente de CORS_ORIGIN; configuração incorreta pode abrir conexões de domínios não confiáveis.
  • Conclusão:
    • Existem boas configurações base, mas a ausência de validação global e a desativação de throttling em rotas críticas são pontos fracos.

6. Dependências Vulneráveis

  • O que foi verificado:
    • Foi feita apenas inspeção estática dos package.json (backend, frontend e webhook-proxy).
    • As versões usadas (NestJS 11, Angular 21, socket.io 4.8.x, axios 1.13.x, etc.) são relativamente recentes.
  • Limitações:
    • Não foi possível rodar npm audit / pnpm audit / scanners SCA neste ambiente (sem acesso à base de vulnerabilidades em tempo real).
    • Portanto, não há garantia de que não existam CVEs conhecidas afetando as versões atuais.
  • Recomendações:
    • Rodar em ambiente de CI / dev:
      • npm audit --omit=dev no backend e frontend.
      • npm outdated para avaliar updates menores/patch.
    • Considerar o uso de ferramentas SCA contínuas (Dependabot, Renovate, Snyk, etc.).

7. Exposição de Dados Sensíveis

  • Identificado:
    • Senhas de usuários em texto claro (visible_password) no banco.
    • users.instance_token (token de instância do WhatsApp Uazapi) armazenado em texto claro via UsersService.updateInstanceToken.
    • Tokens de WhatsApp Meta:
      • whatsapp_meta_connections.access_token armazenado em texto claro no banco.
      • META_SYSTEM_USER_TOKEN mantido apenas em variável de ambiente (OK), mas usado extensivamente em chamadas externas.
    • Logs contendo:
      • IDs de usuários, usernames, roles.
      • Mensagens de erro completas de APIs externas (podendo conter detalhes internos).
  • Riscos:
    • Vazamento de backups ou dumps de banco expõem:
      • Senhas reais (por causa de visible_password).
      • Tokens de integrações com WhatsApp/Uazapi/Meta.
  • Ações recomendadas:
    • Remover visible_password e resetar senhas dos usuários afetados.
    • Criptografar em repouso tokens de integrações (campo criptografado na tabela, com chave de criptografia gerenciada).
    • Reduzir a verbosidade de logs em produção e mascarar campos sensíveis.

8. Quebra de Controle de Acesso

  • Casos principais:
    • Atualização de canal de contatos (updateContactChannel) sem verificação de account_id.
    • API de permissões permitindo auto‑elevação de privilégios.
    • Endpoints WhatsApp expondo operações críticas baseadas apenas em username.
    • Possíveis consultas/atualizações em outros services que usam somente id sem account_id (risco multi‑tenant).
  • Conclusão:
    • Há múltiplas quebras de controle de acesso, tanto horizontais (entre usuários da mesma conta) quanto verticais (seller → admin).
    • É necessário um esforço de revisão sistemática das queries e de quem pode chamar cada endpoint.

9. Falta de Criptografia Adequada

  • Positivo:
    • Uso de bcrypt com salt para hash de senhas na coluna password.
    • Uso de HTTPS/TLS pressuposto na infra (não gerenciado diretamente pelo código).
  • Problemas:
    • Armazenamento em texto claro de:
      • Senhas (visible_password).
      • Tokens de acesso a integrações (WhatsApp Meta, Uazapi).
    • Não há criptografia em repouso desses segredos no banco.
  • Recomendações:
    • Manter apenas hashes irreversíveis para senhas.
    • Introduzir camada de criptografia simétrica para tokens sensíveis no banco, com rotação de chaves.

10. Logging e Monitoramento Insuficientes

  • Pontos positivos:
    • AllExceptionsFilter centraliza e estrutura logs de erro.
    • ActivityLogsService registra eventos de negócio relevantes (criação/remoção de anexos, ações em cards etc.).
    • Diversos serviços logam operações importantes (WhatsApp, webhooks, worker/proxy).
  • Possíveis melhorias:
    • Não há camadas explícitas de:
      • Detecção de tentativas repetidas de login (além do Throttler genérico).
      • Alertas em caso de falhas de autenticação repetidas ou erros críticos (integrado a sistemas de monitoramento).
    • Logs podem conter dados sensíveis se não forem sanitizados antes de ir para provedores externos.
  • Conclusão:
    • Logging existe e é razoavelmente estruturado, mas faltam:
      • Integração com ferramentas de observabilidade/alertas.
      • Uma política clara de mascaramento de dados sensíveis e retenção de logs.

Backend – Vulnerabilidades Críticas

  • Armazenamento de senhas em texto claro (visible_password)

    • O serviço de usuários e o serviço de sistema armazenam a senha original em campo visible_password no banco:
      • UsersService.create e createSeller inserem visible_password com a senha em texto claro.
      • UsersService.updatePassword atualiza visible_password com a nova senha em texto claro.
      • SystemService.createCustomerAdmin também grava visible_password com a senha fornecida.
    • Impactos:
      • Qualquer acesso ao banco (DBA, invasor, vazamento de backup) revela instantaneamente as senhas reais dos usuários.
      • Usuários que reutilizam senhas entre sistemas têm contas externas comprometidas.
      • Quebra completa de requisitos de LGPD/GDPR e boas práticas de segurança.
    • Gravidade: Crítica – deve ser removido imediatamente, migrando para armazenamento apenas do hash.
  • Endpoints WhatsApp sem autenticação (públicos)

    • WhatsappController não usa @UseGuards(AuthGuard('jwt')) nem outro guard.
    • Endpoints acessíveis anonimamente:
      • POST /whatsapp/connect – inicia/gera instância WhatsApp para um username.
      • GET /whatsapp/status – obtém status por token ou username.
      • PUT /whatsapp/ai-settings – altera flags de IA de um usuário por username.
      • PUT /whatsapp/test-numbers – altera números de teste por username.
      • GET /whatsapp/ai-settings, GET /whatsapp/account-settings, PUT /whatsapp/account-settings, PUT /whatsapp/professionals, PUT /whatsapp/payment-methods – expõem e permitem alterar configurações de conta com base apenas no username.
    • Impactos:
      • Qualquer pessoa que saiba (ou consiga adivinhar) username pode:
        • Iniciar/roubar conexão WhatsApp de uma loja.
        • Ler configurações sensíveis de conta.
        • Alterar configurações de IA, profissionais, formas de pagamento etc.
      • Possível sequestro de conta e vazamento de dados de contatos/conversas via integrações.
    • Gravidade: Crítica – todos estes endpoints precisam ser protegidos por AuthGuard('jwt') e validações de autorização por account_id.
  • Escalada de privilégios via API de permissões

    • PermissionsController está protegido por JWT, porém sem checagem de papel (role):
      • GET /permissions/:userId – qualquer usuário autenticado pode ler permissões de qualquer outro usuário.
      • PUT /permissions/:userId – qualquer usuário autenticado pode atualizar permissões de qualquer usuário (incluindo si próprio).
    • O PermissionsService.updatePermissions não faz nenhum controle de quem está alterando, apenas grava as flags.
    • Impactos:
      • Um usuário com papel seller pode se dar acesso total a outros painéis (via can_view_other_boards, can_edit_other_boards etc.).
      • Permite contornar qualquer lógica de autorização baseada nessas permissões.
    • Gravidade: Crítica – é necessário restringir estes endpoints a admin/owner/superadmin (e ainda assim com regras de negócio claras).
  • Chave de API global com privilégios de superadmin

    • ApiKeyStrategy autentica requisições via header X-API-Key usando um único valor process.env.API_KEY.
    • Em caso de sucesso:
      • O usuário retornado tem role: 'admin', is_super_admin: true, via_api_key: true.
      • Esse “usuário” tem acesso total aos recursos protegidos pelo guard JwtOrApiKeyGuard.
    • Impactos:
      • Vazamento da variável API_KEY (log, CI, repositório, fornecedor) compromete toda a aplicação.
      • Não há rotação granular por cliente/integração; tudo depende de um único segredo.
    • Gravidade: Alta – exigir chaves por tenant/integração, com escopo e rotação, ou substituir por OAuth/jwt de serviço.
  • Quebra de controle de acesso em atualização de canal de contato

    • ChannelsController.updateContactChannel (rota PUT /channels/contact/:contactId) não usa account_id do usuário autenticado.
    • ChannelsService.updateContactChannel apenas:
      • Verifica se o channelId existe.
      • Atualiza o contato (contacts.id = contactId) sem checar se o contato pertence à mesma conta (account_id).
    • Impactos:
      • Usuário autenticado pode alterar o canal (channel_id) de contatos de outros tenants, se souber o contactId.
      • Embora IDs sejam UUIDs, podem ser obtidos via outras APIs/erros/logs.
    • Gravidade: Alta – precisa validar contacts.account_id = req.user.account_id antes de atualizar.
  • Ausência de validação de entrada centralizada

    • O projeto usa class-validator / class-transformer, mas:
      • Não há ValidationPipe global configurado em main.ts.
      • A maioria dos controllers recebe @Body() e @Query() como objetos “soltos” (tipados só em TypeScript ou any).
    • Impactos:
      • Falta de validação de tipos, tamanhos, formatos e whitelisting de campos.
      • Maior superfície para:
        • Quebras lógicas (valores inesperados).
        • DoS (payloads grandes em campos não controlados).
        • Problemas de segurança em integrações a jusante (por exemplo, dados não sanitizados indo para terceiros).
      • O uso de Knex com bindings minimiza SQL Injection, mas não elimina outros vetores.
    • Gravidade: Média/Alta – recomendável habilitar ValidationPipe global com whitelist e forbidNonWhitelisted.
  • Endereços multi-tenant nem sempre filtrados por account_id

    • Em vários serviços/controladores a conta é considerada (por exemplo, BoardsService, StatisticsService, TasksService, CommentsService usam account_id).
    • Porém existem pontos onde a operação é feita apenas por id sem forçar account_id, ou sem passar o account_id para o service (por exemplo, alguns métodos de CardsService, ContactsService, ChannelsService).
    • Impactos:
      • Risco de acesso/alteração de registros de outros tenants se o ID for conhecido.
      • Dificulta garantir isolamento total de dados entre contas.
    • Gravidade: Média – revisar sistematicamente se todos os SELECT/UPDATE/DELETE multi-tenant usam sempre account_id do usuário autenticado.

Backend – Outros Riscos e Observações

  • Webhooks com rate limit desativado

    • WebhooksController (/webhooks/n8n) e WhatsappMetaWebhookController (/webhooks/meta/whatsapp) usam @SkipThrottle().
    • Autenticação:
      • Webhooks N8N usam WebhookGuard com header x-webhook-token comparado a N8N_WEBHOOK_SECRET usando timingSafeEqual (bom).
      • Webhook Meta usa META_WHATSAPP_VERIFY_TOKEN na verificação de assinatura e tenta validar x-hub-signature-256 com HMAC.
    • Impactos:
      • Ataques de DoS são possíveis se alguém descobre o endpoint (mesmo sem quebrar o segredo), pois não há rate limit adicional.
      • Dependência forte da confidencialidade das variáveis de ambiente.
    • Gravidade: Média – aceitável para webhooks de alta taxa, mas recomenda-se filtros adicionais (IP allowlist, camada WAF/CDN).
  • Logs potencialmente verbosos com dados sensíveis

    • AllExceptionsFilter loga detalhes de erros incluindo:
      • URL, método, mensagem, tipo de erro, e usuário (id, username, role).
    • Serviços de WhatsApp logam respostas de erro completas da API externa.
    • Impactos:
      • Em ambientes de produção sem adequado gerenciamento de logs, informações sensíveis podem ir para provedores de log externos.
      • Não detectei logs diretos de tokens/senhas, mas vale revisar formatos e reter o mínimo necessário.
    • Gravidade: Baixa/Média – monitorar sanitização de logs e política de retenção/armazenamento.
  • Configuração de CORS dependente de variável de ambiente

    • main.ts:
      • parseCorsOrigins impede CORS_ORIGIN='*' em produção (bom).
      • Em dev, permite '*' ou origens padrão http://localhost:4200/4201.
    • Impactos:
      • Se CORS_ORIGIN for configurado de forma muito ampla em produção (por exemplo, incluindo domínios terceiros não confiáveis), aumenta risco de ataques cross-origin (principalmente se no futuro usar cookies).
    • Gravidade: Baixa – desde que CORS_ORIGIN seja bem gerenciado em produção.

Frontend – Vulnerabilidades e Riscos

  • Armazenamento de JWT em localStorage

    • AuthService armazena o access_token em localStorage:
      • accessToken = signal<string | null>(localStorage.getItem('access_token'));
      • localStorage.setItem('access_token', token);
    • Outros serviços leem diretamente do localStorage (vehicles.service, boards.service, features.service etc.).
    • Impactos:
      • Em caso de qualquer XSS, o atacante pode ler o token e assumir a sessão do usuário.
      • Tokens não são protegidos contra exfiltração como seriam em cookies HttpOnly.
    • Gravidade: Alta em cenários com risco real de XSS – ideal migrar para cookies HttpOnly + SameSite + Secure, ou endurecer fortemente contra XSS.
  • Autorização confiando demais em guards de frontend

    • Guards como adminOrOwnerGuard (permission.guard.ts) usam apenas o role decodificado do JWT no cliente.
    • O backend, contudo:
      • Não valida papel em alguns endpoints sensíveis (por exemplo, permissões, alguns endpoints de sistema e WhatsApp).
    • Impactos:
      • Mesmo que a UI esconda botões e rotas, usuários mal-intencionados podem chamar APIs diretamente (via Postman, curl, etc.).
      • A segurança não pode depender apenas de guards do frontend.
    • Gravidade: Alta – o backend precisa replicar (e reforçar) a lógica de autorização que hoje só existe na UI.
  • Uso de localStorage para cache de feature flags

    • FeaturesService salva feature_flags em localStorage.
    • Impactos:
      • Risco é menor (não são segredos), mas qualquer XSS pode alterar flags e mudar comportamento da UI (por exemplo, esconder áreas de visibilidade).
    • Gravidade: Baixa – aceitável, desde que o backend continue validando permissão independentemente das flags.

Recomendações de Correção (Resumo)

  • Senhas

    • Remover completamente o campo visible_password do código e do banco.
    • Criar migração para limpar esse campo e, idealmente, excluir a coluna.
  • Autenticação e Autorização

    • Proteger WhatsappController (e qualquer outro controller sensível) com AuthGuard('jwt').
    • Em todos os endpoints administrativos/sistema (permissões, system bootstrap, WhatsApp oficial, etc.), checar:
      • Papel: admin / owner / is_super_admin.
      • account_id coerente com o recurso acessado.
    • Restringir PermissionsController.updatePermissions e similares a perfis autorizados.
  • Multi-tenant

    • Padronizar todas as consultas/atualizações para sempre incluírem account_id do usuário autenticado.
    • Revisar especialmente services que recebem apenas id (como updateContactChannel).
  • Chaves e Webhooks

    • Substituir a chave única API_KEY por um modelo de múltiplas chaves por tenant/integração com escopo e revogação.
    • Para webhooks com @SkipThrottle, considerar:
      • Proteção adicional via IP allowlist, WAF ou API Gateway.
      • Monitoramento ativo de volume e abuso.
  • Validação de Entrada

    • Habilitar ValidationPipe global com:
      • whitelist: true
      • forbidNonWhitelisted: true
      • transform: true
    • Criar DTOs com class-validator para todos os endpoints que recebem body/query sensíveis.
  • Frontend

    • Considerar migrar de localStorage para cookies HttpOnly/SameSite para o JWT, ou aplicar CSP rigorosa e mitigação forte de XSS.
    • Tratar guards apenas como camada de UX; toda autorização real deve ser replicada/forçada no backend.

Conclusão

O projeto já possui diversas boas práticas (Helmet, Throttler, CORS configurável, uso de JWT, secrets via .env), mas as vulnerabilidades críticas destacadas (principalmente senhas em texto claro, endpoints WhatsApp públicos, escalada de privilégios via permissões e chave de API global superadmin) expõem a aplicação a comprometimento total em caso de exploração.

As correções sugeridas acima devem ser priorizadas em ordem de gravidade, começando pelas que podem levar à tomada completa do ambiente ou vazamento massivo de dados.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors