
Persistência de Sessão do listmonk Após Redefinição e Alteração de Senha
Persistência de Sessão do listmonk Após Redefinição e Alteração de Senha
Encontrei este problema ao revisar o listmonk, um gerenciador open-source de newsletters e listas de e-mail, com uma pergunta simples de segurança em mente:
Quando um usuário altera ou redefine a senha, o aplicativo realmente encerra as sessões já emitidas?
Neste caso, a resposta foi não.
Sessões autenticadas emitidas anteriormente permaneceram válidas tanto após:
Isso significava que um cookie de sessão roubado poderia sobreviver exatamente aos eventos de segurança em que os usuários confiam para recuperar a conta.
O problema foi aceito e recebeu a identificação CVE-2026-34828.
Projeto: listmonk no GitHub
CVE: CVE-2026-34828
Isso afetou o listmonk, um projeto amplamente adotado com 5M+ de pulls no Docker.
sessão autenticada roubada → vítima redefine ou altera a senha → sessão antiga permanece válida → atacante mantém acesso à conta após a recuperação da credencial
O listmonk é um gerenciador auto-hospedado de listas de e-mail e newsletters.
Ele oferece:
Isso significa que seu modelo de sessão é um limite de segurança real.
A pergunta importante aqui não era se o listmonk suporta redefinição de senha.
A verdadeira pergunta era:
A redefinição ou alteração de senha realmente revoga a persistência do atacante se uma sessão já tiver sido roubada?
Neste caso, não.
Muitas análises de segurança focam de forma demasiadamente restrita em bypass de login e escalonamento de privilégio óbvio.
Isso deixa passar uma classe importante de fraquezas:
falhas de recuperação
Se um usuário altera ou redefine a senha, essa ação deve ser significativa.
Ela deve reduzir a confiança em credenciais antigas e no estado de autenticação antigo.
Se um atacante já possui uma sessão válida e essa sessão sobrevive ao evento de recuperação, então a vítima não recuperou a conta completamente.
Este foi o problema aqui.
Não era um bug de validação de login. Não era um problema de criptografia. Não era uma falha de hash de senha.
Era uma falha no ciclo de vida da sessão:
Isso é suficiente para criar uma vulnerabilidade real.
Não abordei o listmonk atacando endpoints aleatoriamente na esperança de que um deles caísse.
O caminho mais forte era identificar primeiro o limite de confiança de maior valor.
Para software com forte dependência de autenticação, um dos melhores limites a testar é este:
Alterações de conta sensíveis à segurança revogam sessões anteriormente confiáveis?
Essa pergunta geralmente se torna interessante em torno de:
No listmonk, o sinal mais forte veio dos dois primeiros.
Foi aí que o problema ficou claro.
O bug não era que as alterações de senha falhavam.
O bug era que as sessões sobreviviam a elas.
Pela revisão do código-fonte, o fluxo de redefinição de senha:
mas não havia revogação visível de sessões mais antigas.
O mesmo padrão aparecia no fluxo autenticado de alteração de senha:
Esse comportamento correspondia exatamente aos resultados reais.
As áreas de código relevantes que revisei foram:
cmd/auth.go para o comportamento de esqueci/redefinircmd/users.go para atualizações de perfil autenticadasinternal/core/users.go para o tratamento de atualização de senhaPorque o roubo de sessão é uma condição de ataque real.
Uma vez que um atacante obtém um cookie de sessão autenticado válido por qualquer meio, como:
a vítima deveria ser capaz de encerrar a persistência do atacante alterando ou redefinindo a senha.
Aqui, ela não conseguia.
A cadeia de ataque era direta:
Essa é toda a vulnerabilidade.
A distinção importante é a persistência após a recuperação.
Muitos aplicativos tratam a alteração de senha como um evento puramente no nível da credencial. Isso não é suficiente.
A verdadeira pergunta não é:
“O valor da senha mudou no armazenamento?”
A verdadeira pergunta é:
“A relação de confiança associada a sessões mais antigas foi revogada?”
No listmonk, não foi.
Isso transforma o que poderia ser uma manutenção comum de conta em uma recuperação de segurança incompleta.
Essa é a diferença entre:
Validei o problema em dois fluxos separados.
Primeiro, criei um usuário de teste normal e fiz login, salvando o cookie de sessão autenticado.
Em seguida, acionei o fluxo de esqueci a senha, capturei o link de redefinição e redefini a senha.
Após a redefinição:
Uma requisição de validação representativa era assim:
GET /api/profile HTTP/1.1
Host: 127.0.0.1:9000
Cookie: session=<old_pre_reset_session>
E o servidor ainda retornava:
HTTP/1.1 200 OK
Content-Type: application/json
com o perfil autenticado.
Isso estabeleceu a afirmação central:
Em seguida, validei a mesma classe de bug no fluxo autenticado de alteração de senha.
Fiz login duas vezes como o mesmo usuário e salvei duas sessões autenticadas válidas:
Usando a sessão A, alterei a senha pelo endpoint de atualização de perfil.
Exemplo de requisição:
PUT /api/profile HTTP/1.1
Host: 127.0.0.1:9000
Cookie: session=<session_A>
Content-Type: application/json
{
"name":"victim1",
"email":"[email protected]",
"password":"VictimChanged123"
}
Depois disso:
Uma requisição de acompanhamento usando a sessão B ainda retornava dados autenticados de /api/profile.
Isso provou que o problema não se limitava ao caminho de esqueci/redefinir.
Também afetava alterações normais de senha autenticadas.
Uma reprodução já teria sido suficiente para mostrar um problema.
Mas validar os dois fluxos importava por dois motivos.
Mostrou que o bug não estava isolado a um caminho de recuperação de caso extremo.