
Persistenza della sessione di listmonk dopo il reset della password e il cambio della password
Persistenza delle sessioni di listmonk dopo il reset e la modifica della password
Ho trovato questo problema mentre esaminavo listmonk, un gestore open-source di newsletter e mailing list, con una semplice domanda di sicurezza in mente:
Quando un utente modifica o resetta una password, l'applicazione termina effettivamente le sessioni già emesse?
In questo caso, la risposta è stata no.
Le sessioni autenticate emesse in precedenza sono rimaste valide dopo entrambe le azioni:
Ciò significava che un cookie di sessione rubato poteva sopravvivere esattamente agli eventi di sicurezza su cui gli utenti fanno affidamento per recuperare il proprio account.
Il problema è stato accettato e gli è stata assegnata la CVE-2026-34828.
Progetto: listmonk su GitHub
CVE: CVE-2026-34828
Il problema ha interessato listmonk, un progetto ampiamente adottato con 5M+ pull Docker.
stolen authenticated session → victim resets or changes password → old session remains valid → attacker retains account access after credential recovery
listmonk è un gestore self-hosted di mailing list e newsletter.
Offre:
Ciò significa che il suo modello di sessione è un vero confine di sicurezza.
La domanda importante qui non era se listmonk supporta il reset della password.
La vera domanda era:
Il reset o la modifica della password revocano effettivamente la persistenza dell'attaccante se una sessione è già stata rubata?
In questo caso, non lo faceva.
Molte revisioni di sicurezza si concentrano in modo troppo ristretto sui bypass di login e sull'escalation dei privilegi più ovvia.
Questo fa perdere di vista un'importante classe di debolezze:
fallimenti del recupero
Se un utente modifica o resetta una password, quell'azione dovrebbe avere un significato reale.
Dovrebbe ridurre la fiducia nelle credenziali precedenti e nel vecchio stato di autenticazione.
Se un attaccante possiede già una sessione valida e quella sessione sopravvive all'evento di recupero, allora la vittima non ha realmente recuperato completamente l'account.
Questo era il problema qui.
Non era un bug di validazione del login. Non era un problema crittografico. Non era un errore nell'hash delle password.
Era un fallimento del ciclo di vita delle sessioni:
Questo è sufficiente a creare una vulnerabilità reale.
Non ho affrontato listmonk colpendo endpoint a caso e sperando che qualcuno cedesse.
Il percorso più solido era identificare prima il confine di fiducia di maggior valore.
Per software fortemente incentrati sull'autenticazione, uno dei migliori confini da testare è questo:
Le modifiche all'account sensibili dal punto di vista della sicurezza revocano le sessioni precedentemente considerate affidabili?
Quella domanda di solito diventa interessante in relazione a:
In listmonk, il segnale più forte è arrivato dai primi due.
È lì che il problema è diventato evidente.
Il bug non era che le modifiche alla password fallivano.
Il bug era che le sessioni sopravvivevano a esse.
Dalla revisione del codice sorgente, il flusso di reset della password:
ma non c'era alcuna revoca visibile delle sessioni precedenti.
Lo stesso schema appariva nel flusso autenticato di modifica della password:
Questo comportamento corrispondeva esattamente ai risultati reali.
Le aree di codice rilevanti che ho esaminato sono state:
cmd/auth.go per il comportamento di password dimenticata/resetcmd/users.go per gli aggiornamenti autenticati del profilointernal/core/users.go per la gestione dell'aggiornamento della passwordPerché il furto di sessione è una condizione di attacco reale.
Quando un attaccante ottiene un cookie di sessione autenticata valido con qualsiasi mezzo, ad esempio:
la vittima dovrebbe essere in grado di terminare quella persistenza dell'attaccante modificando o resettando la password.
Qui, non poteva.
La catena di attacco era semplice:
Questa è l'intera vulnerabilità.
La distinzione importante è la persistenza dopo il recupero.
Molte applicazioni trattano la modifica della password come un evento puramente a livello di credenziali. Non è sufficiente.
La vera domanda non è:
“Il valore della password è cambiato nell'archivio?”
La vera domanda è:
“La relazione di fiducia associata alle sessioni precedenti è stata revocata?”
In listmonk, non lo è stata.
Questo trasforma quella che sarebbe potuta essere una normale manutenzione dell'account in un recupero di sicurezza incompleto.
Questa è la differenza tra:
Ho validato il problema in due flussi separati.
Innanzitutto, ho creato un normale utente di test e ho effettuato l'accesso, salvando il cookie di sessione autenticata.
Poi ho attivato il flusso di password dimenticata, catturato il link di reset e resettato la password.
Dopo il reset:
Una richiesta di validazione rappresentativa appariva così:
GET /api/profile HTTP/1.1
Host: 127.0.0.1:9000
Cookie: session=<old_pre_reset_session>
E il server restituiva ancora:
HTTP/1.1 200 OK
Content-Type: application/json
con il profilo autenticato.
Questo ha confermato l'affermazione principale:
Ho poi validato la stessa classe di bug nel flusso autenticato di modifica della password.
Ho effettuato l'accesso due volte come lo stesso utente e ho salvato due sessioni autenticate valide:
Usando la sessione A, ho modificato la password tramite l'endpoint di aggiornamento del profilo.
Richiesta di esempio:
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"
}