Skip to content

Vulnerabilidade de XSS persistente em endpoint de criação/edição de uma conversa

Descrição do Problema

Foi identificada uma vulnerabilidade Cross-Site Scripting (XSS) do tipo Persistente (Stored XSS), especificamente nos campos "Text to be displayed as welcome" e "Text to be presented at the end of the collection" durante a criação e/ou edição de conversas.

Essa falha permite que um atacante insira código JavaScript malicioso que é armazenado no banco de dados e posteriormente executado no navegador de qualquer usuário que acesse a conversa.


Contexto e Impacto

  • Tipo de vulnerabilidade: XSS Persistente (Stored XSS)

  • Localização:

    • conversation-welcome.jinja2 — linha 48
    • card.jinja2 — linha 18
  • Causa raiz:

    1. Falta de sanitização no backend.
    2. Uso do filtro |safe no Jinja2, que impede o escaping de HTML.

Essa falha viola o princípio de Defesa em Profundidade (Defense in Depth) e permite a execução de código arbitrário sob o domínio da aplicação.


Prova de Conceito (PoC)

Passos para reprodução:

  1. Autentique-se como um usuário com permissão para criar conversas.

  2. Obtenha o cookie de sessão e os tokens CSRF da aplicação (via DevTools).

  3. Envie uma requisição POST direta ao endpoint:

    /boards/{username}/conversations/add/

    ou

    /boards/{username}/conversations/{id}/{slug}/edit/
  4. No campo welcome_message, insira o payload malicioso:

    <script>alert('XSS Reproduzido!');</script>
  5. Acesse a URL da conversa criada:

    /boards/{username}/conversations/{id}/{slug}/welcome/
  6. Observe a execução automática do script no navegador.

Resultado esperado: O alerta é exibido, comprovando a execução do código injetado e a persistência da vulnerabilidade.

Extra: A descrição dessa issue é limitada, a apesar de indicar totalmente o problema encontrado. Logo, se forem necessárias mais informações sobre a execução da vulnerabilidade em PoC, com imagens e ferramentas, pode-se acessar o documento em PDF no OneDrive: Relatório-XSS-V1_0-EJ.pdf


Causa Técnica

  • Falta de sanitização no backend antes do armazenamento no banco de dados.
  • Confiança indevida na sanitização realizada pelo frontend.
  • Uso do filtro |safe no Jinja2, que permite renderização direta de HTML sem escaping.

Recomendação / Proposta de Mitigação

Implementar sanitização obrigatória no backend para todo conteúdo Rich Text antes de salvar no banco de dados.

Ações sugeridas:

  1. Usar biblioteca de sanitização: Para Python/Django, recomenda-se a biblioteca nh3.

  2. Configurar allow-list restrita:

    • Permitir apenas tags HTML seguras (<b>, <i>, <p>, <a>, etc.)
    • Remover atributos perigosos (onclick, onerror, javascript:).
  3. Aplicar sanitização nos endpoints vulneráveis:

    /boards/{username}/conversations/add/
    /boards/{username}/conversations/{id}/{slug}/edit/
  4. Evitar o uso direto de |safe no Jinja2 para dados dinâmicos sem validação.


Severidade e Risco

Categoria Nível
Impacto Alto — execução arbitrária de código no cliente
Probabilidade de exploração Baixa
Exploração requer autenticação Sim
Tipo Stored XSS